Sed command garbled question

for j in $(cat ${list_B})
do
to_replace_2=$(grep $j ${useralias}_2)
sed "s/^${j}/${to_replace_2}/p" ${entries} > ${entries}_2
mv ${entries}_2 ${entries}
done

Hi,
I've the above sed command running in a script. Its basically looping through a file and replacing its beginning of line grep'd match in another file.. It works 90% of the time but sometimes i'll get a garbled error like the one below.. The var ${to_replace_2} can contain any random string of characters. I've also tried to use different separators but that didn't work either..

Not sure why it works for some and not others..

sed: command garbled: s/^CCMAIL/CCMAIL=wa990097

Can anyone help?

You know that some characters are special to seds command language, don't you? For instance:

x="abc" ; y="def"
sed "s/$x/$y/" /path/to/input > /path/to/output

will work as expected, but:

x="ab/c" ; y="def"
sed "s/$x/$y/" /path/to/input > /path/to/output

will not (and changing the delimiters will only move the problem around, because now some other character will cause the problem). The following even will work, but not in the expected way:

x="ab*c" ; y="def"
sed "s/$x/$y/" /path/to/input > /path/to/output

The only real solution to this is to escape the problematic characters and this is done by prepending them with backslashes:

x="ab/c" ; y="def"
x="$(sed 's/\/\\&/')"
sed "s/$x/$y/" /path/to/input > /path/to/output

Here is a quick (and unrefined!) solution which escapes the problematic characters. Use at your own risk:

sed 's/\[/\\&/g
     s/\]/\\&/g
     s/[/*?{}]/\\&/g'

I hope this helps.

bakunin

Hi thanks for the response.. I do understand that sed has some characters that are special to the command language..

I don't quite see how your above example would fit into my for loop?

Are you saying it should look like the below?

for j in $(cat ${list_B})
do
to_replace_2=$(grep $j ${useralias}_2)
to_replace_2="(sed 's/\/\\&/')"
sed "s/^${j}/${to_replace_2}/p" ${entries} > ${entries}_2
mv ${entries}_2 ${entries}
done

Almost. In fact you have to process the variables contents before using them in a sed statement:

for j in $(cat ${list_B}) ; do
     to_replace_2="$( grep $j ${useralias}_2 |\
                      sed 's/\[/\\&/g
                           s/\]/\\&/g
                           s/[/*?{}]/\\&/g' \
                    )"
     j="$( echo $j |\
           sed 's/\[/\\&/g
                s/\]/\\&/g
                s/[/*?{}]/\\&/g' \
         )"
     sed "s/^${j}/${to_replace_2}/p" ${entries} > ${entries}_2
     mv ${entries}_2 ${entries}
done

I hope this helps.

bakunin

PS: i just noticed you can now use sed instead of grep: instead of

to_replace_2="$( grep $j ${useralias}_2 |\
                 sed 's/\[/\\&/g
                      s/\]/\\&/g
                      s/[/*?{}]/\\&/g' \
               )"

You just use:

to_replace_2="$(sed -n '/'"${useralias_2}"'/ {
                              s/\[/\\&/g
                              s/\]/\\&/g
                              s/[/*?{}]/\\&/g
                              p
                              q
                        }'
               )"

Hi bakunin,

I tried the first way you gave and it still doesn't seem to fix the issue.. (Although it did help me out further down my script..) Can't figure out why it stalls on one particular file.. It's formatted the exact same way as everything else..

Also tried your sed suggestion but I ended up just getting a load of the following:

My code is as follows but still getting a garbled command

for j in $(cat ${list_B})
do
     to_replace_2="$( grep $j ${useralias}_2 |\
                      sed 's/\[/\\&/g
                           s/\]/\\&/g
                           s/[/*?{}]/\\&/g' \
                    )"
     j="$( echo $j |\
           sed 's/\[/\\&/g
                s/\]/\\&/g
                s/[/*?{}]/\\&/g' \
         )"
     sed "s/${j}/${to_replace_2}/1" ${entries} > ${entries}_2
     mv ${entries}_2 ${entries}
done

sed: command garbled: s/CCMAIL/CCMAIL=wa990097

useless use of backticks

while read FILENAME
do
...
done < inputfile

Try replacing sed with echo just to make absolutely positive you're giving it the parameters you think you are.

Hi,
the garbled command is showing what i need.. I'm trying to replace

CCMAIL with CCMAIL=wa990097 but i don't know why it won't do it.. It works for files I'm working with..

What, exactly, did it show then?

echoing out the results was good advice... I needed to replace $j with $j$.. The grep was picking up multiples..

Thanks everyone for the help...