Sed/replace using variable

Hello everyone,

In one of my shell script I am doing sed/replace using a variable to find a string in a file & replace it with another string in same file.

The challenge which I am facing is that, the variable which I am using with "sed" is having one of character as

"/"

Here is below how I am using the same,

Firstly, I am parsing "fdisk -l" output so that I will get the output in below format & assiging it to variable as below,

NewDisk=`fdisk -l | grep LINUX | egrep -v '\*|LVM' | awk '{print $1}' | sed 's/\/dev\///'`

With above command the variable

$NewDisk

getting assigned value

csicc/c0d0p5

Now, I am doing sed/replace as below,

sed -i "s/^cdrom/harddrive --partition=${NewDisk} --dir=\//" FILENAME.txt

However this command is failing, I guess because the variable

$NewDisk

contains "/" & which need to be escaped somehow, which I don't know how to do it.

I tried various options but no luck, every time it is failing with below error,

sed: -e expression #1, char 38: unknown option to 's`

Even I tried to add escape before "/" as below,

fdisk -l | grep LINUX | egrep -v '\*|LVM' | awk '{print $1}' | sed 's/\/dev\///' | sed "s/\//\\\//g"

when I run above command, on command line it works fine & display output as

csicc\/c0d0p5

, but it fails with above error when I try to get this in variable.

Please suggest me how to fix this.

Regards,
Uday

In sed you can replace the slash of the substitute command with almost any character .

$ echo "Turn forward // into dashes" | sed 's/\//-/g' 
Turn forward -- into dashes

Using | instead of / :

$ echo "Turn forward // into dashes" | sed 's|/|-|g' 
Turn forward -- into dashes

Another thing is that you may need extra backslashes within double quotes. So best to use single quotes..

$ echo "Turn forward // into backslashes" | sed 's/\//\\/g' 
Turn forward \\ into backslashes
$ echo "Turn forward // into backslashes" | sed "s/\//\\/g" 
sed: 1: "s/\//\/g": unterminated substitute in regular expression
$ echo "Turn forward // into backslashes" | sed "s/\//\\\\/g" 
Turn forward \\ into backslashes
$ echo "Turn forward // into backslashes" | sed 's|/|\\|g' 
Turn forward \\ into backslashes
1 Like

If you're doing grep | sed | grep -v | awk | sed | cut | kitchen | sink, just use awk and be done with it.

fdisk prints 'Linux' on my system, not LINUX, but adjust to taste.

$ fdisk -l | awk '/Linux/ && !/[*]|LVM/ {sub("/dev/", ""); print $1 }'

sda1
sda2
sda3
sda5
sda6
sda7
sdb1
sdb2
sdb3
sdc1
sdc2
sdc3

$
1 Like

Don't see LINUX or LVM in the output of fdisk -l . Maybe you are using other than GNU Linux?

What I see here...

NewDisk=`fdisk -l | grep Linux | egrep -v '\*|LVM' |awk '{print $1}' | sed 's/\/dev\///'`
echo $NewDisk
# -- produces --
# sda5 sda6 sda7 sda10 sda11 sda12 sdf2 sdf5 sdf6 sdf7 sdf8 sdf9 sdf10 sdf11

# (using sed -e to debug)
sed -e "s/^cdrom/harddrive --partition=$NewDisk --dir=\//"
# -- produces --
# error

In my case, $NewDisk appears to sed as a space separated list of commands, which are bogus...
The fix for me would be to make $NewDisk an array and access by [index]

NewDisk=(`fdisk -l | grep Linux | egrep -v '\*|LVM' |awk '{print $1}' | sed 's/\/dev\///'`)
sed -e "s/^cdrom/harddrive --partition=${NewDisk[0]} --dir=\//"

In your case, making $NewDisk=csicc/c0d0p5 like you reported, still throws an error because sed sees the /slash in csicc/c0d0p5 as a delimiter...
So change the delimiter in sed from / to |...(ala Scrutinizer post #2)

NewDisk=csicc/c0d0p5
sed -e "s|^cdrom|harddrive --partition=$NewDisk --dir=\/|"
-- produces --
harddrive --partition=csicc/c0d0p5 --dir=/

Give it a go and lemme know if I need to make any edits here.

Thx

1 Like

Using

|

instead of

/

worked like charm.

Thanks a ton to Scrutinizer, Corona688 , ongoto !!!