sedbusyboxdash-shell

How to use SED to find multiple paths in the same line and replace them with a different path?


I have a file with multiple paths in the same line:

cat modules.dep
kernel/mm/zsmalloc.ko:
kernel/crypto/lzo.ko:
kernel/drivers/char/tpm/tpm_vtpm_proxy.ko: kernel/drivers/char/tpm/tpm.ko
kernel/drivers/block/virtio_blk.ko:
kernel/drivers/block/zram/zram.ko: kernel/mm/zsmalloc.ko
kernel/drivers/nvdimm/virtio_pmem.ko: kernel/drivers/nvdimm/nd_virtio.ko
kernel/drivers/nvdimm/nd_virtio.ko:
kernel/drivers/net/virtio_net.ko: kernel/drivers/net/net_failover.ko kernel/net/core/failover.ko
kernel/drivers/net/net_failover.ko: kernel/net/core/failover.ko
extra/virtio_gpu/virtio-gpu.ko: kernel/drivers/virtio/virtio_dma_buf.ko
extra/wlan_simulation/virt_wifi_sim.ko: kernel/drivers/net/wireless/virt_wifi.ko

I would like to change it to:

/lib/modules/zsmalloc.ko:
/lib/modules/lzo.ko:
/lib/modules/tpm_vtpm_proxy.ko: /lib/modules/tpm.ko
/lib/modules/virtio_blk.ko:
/lib/modules/zram.ko: /lib/modules/zsmalloc.ko
/lib/modules/virtio_pmem.ko: /lib/modules/nd_virtio.ko
/lib/modules/nd_virtio.ko:
/lib/modules/virtio_net.ko: /lib/modules/net_failover.ko /lib/modules/failover.ko
/lib/modules/net_failover.ko: /lib/modules/failover.ko
/lib/modules/virtio-gpu.ko: /lib/modules/virtio_dma_buf.ko
/lib/modules/virt_wifi_sim.ko: /lib/modules/virt_wifi.ko

But my attempt:

sed -i 's/\(.*\)\//\/lib\/modules\//g' modules.load

works only, if there is just one path per line.

How can I achieve this, via sed, with multiple paths per line?

I am using sed from BusyBox in D(ASH) Standalone.

BusyBox v1.32.1-Magisk (2021-01-21 00:17:27 PST) multi-call binary.

Usage: sed [-i[SFX]] [-nrE] [-f FILE]... [-e CMD]... [FILE]...
or: sed [-i[SFX]] [-nrE] CMD [FILE]...

    -e CMD  Add CMD to sed commands to be executed
    -f FILE Add FILE contents to sed commands to be executed
    -i[SFX] Edit files in-place (otherwise sends to stdout)
        Optionally back files up, appending SFX
    -n  Suppress automatic printing of pattern space
    -r,-E   Use extended regex syntax

If no -e or -f, the first non-option argument is the sed command string.
Remaining arguments are input files (stdin if none).

Solution

  • This sed should work:

    sed -E 's~[^[:blank:]]+/~/lib/modules/~g' modules.dep
    
    /lib/modules/zsmalloc.ko:
    /lib/modules/lzo.ko:
    /lib/modules/tpm_vtpm_proxy.ko: /lib/modules/tpm.ko
    /lib/modules/virtio_blk.ko:
    /lib/modules/zram.ko: /lib/modules/zsmalloc.ko
    /lib/modules/virtio_pmem.ko: /lib/modules/nd_virtio.ko
    /lib/modules/nd_virtio.ko:
    /lib/modules/virtio_net.ko: /lib/modules/net_failover.ko /lib/modules/failover.ko
    /lib/modules/net_failover.ko: /lib/modules/failover.ko
    /lib/modules/virtio-gpu.ko: /lib/modules/virtio_dma_buf.ko
    /lib/modules/virt_wifi_sim.ko: /lib/modules/virt_wifi.ko
    

    [^[:blank:]]+/ finds 1+ non-whitespace characters followed by a / thus matching longest string until it gets a / in each of the multiple string per line.