LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   sed: \ in variable dissappears in append feature (https://www.linuxquestions.org/questions/linux-newbie-8/sed-%5C-in-variable-dissappears-in-append-feature-4175613554/)

say_hi_ravi 09-10-2017 01:02 PM

sed: \ in variable dissappears in append feature
 
I want to append below find command in a file under a line matching a string.

command:
Quote:

find /path/to/dir -type f \( -name '*.gz' -o -name '*.log' \) -mtime + ${days} -exec rm -fr {} \;
File:
Quote:

$ cat disk.sh
for id abc
I am taking a command in variable and then using sed to add command via variable under a line below match.

Quote:

$ COMM=`echo "find /path/to/dir -type f \( -name '*.gz' -o -name '*.log' \) -mtime + ${days} -exec rm -fr {} \;"`

$ sed -i "/for id abc/a ${COMM}" disk.sh
However in output \ dissappears.

Quote:

$ cat disk.sh
for id abc
find /path/to/dir -type f ( -name '*.gz' -o -name '*.log' ) -mtime + ${days} -exec rm -fr {} ;
But variable seem to have captured the whole command perfectly.

Quote:

$ echo ${COMM}
find /path/to/dir -type f \( -name '*.gz' -o -name '*.log' \) -mtime + ${days} -exec rm -fr {} \;

rknichols 09-10-2017 01:44 PM

Yes, the sed command will interpret the backslash itself, and the sequences "\(" and "\)" are just "(" and ")" respectively. If you want the sed command to treat the backslashes literally, you would have to escape each of the with another backslash. But, then the shell will see the sequence "\\" within double quotes, where the backslash keeps its special meaning, and will just replace those two characters with a single backslash. The way you are using single and double quotes, the shell will be also doing that when setting the COMM variable. You can prevent that by reversing your usage of single and double quotes (and getting rid of that useless use of "echo" is a good idea too).
Code:

COMM='find /path/to/dir -type f \\( -name "*.gz" -o -name "*.log" \\) -mtime + ${days} -exec rm -fr {} \\;'
sed -i "/for id abc/a ${COMM}" disk.sh

(I really with this darned forum software would stop occasionally eating backslashes.)

say_hi_ravi 09-10-2017 03:15 PM

Thanks for reply.

Tried to escape using one more \ and got rid of echo too. ${days} gets printed literally instead of its value. Escaping the curly brackets and $ didnt work too.

Also Assigned the command to double quoted variable with escaping \ with one more \. Again the original issue of \ missing :(

rknichols 09-10-2017 04:07 PM

Sorry, I missed that there was a ${days} expansion in that assignment of the COMM variable. You would need to keep that outside of the single quotes:
Code:

COMM='find /path/to/dir -type f \\( -name "*.gz" -o -name "*.log" \\) -mtime + '${days}' -exec rm -fr {} \\;'
                                                                              ^      ^
                                                            end quoted string |      | start a new quoted string

To stay with the double quotes as you orginally had then, each backslash needs to be quadrupled.
Code:

COMM="find /path/to/dir -type f \\\\( -name '*.gz' -o -name '*.log' \\\\) -mtime + ${days} -exec rm -fr {} \\\\;"
Quoting and backslash escapes in strings that are going to be parsed and re-parsed is messy. It's hard to get around without re-structuring what you are doing.

say_hi_ravi 09-10-2017 04:51 PM

Bingo!!

Many Thanks, Sir!!


All times are GMT -5. The time now is 04:55 PM.