Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Escaping characters in variables inside sed expression

Tags:

bash

sed

So im having an issue where this portion of my script is not working. I'm not sure exactly whats going on, but I get the feeling its because I have not escaped certain characters inside the variables. I tried the following with no luck:

crontab -l | sed "s%$CTMP%\*\/$FREQ \* \* \* \* cd $DIR && \.\/$SCRIPT%" | crontab -

Here is whats in each of the variables:

The CTMP variable is just a line from the crontab file

CTMP='*/5 * * * * cd /home/admin/whatever && ./test.sh'

The FREQ variable is the time in minutes setting of the cron file

FREQ=5

The DIR variable is the current working directory

DIR='/home/admin/whatever'

And the SCRIPT variable is just the script file name

SCRIPT='test.sh'

I feel like the issue is the sed statement is not updating the crontab file because it's not escaping the characters it needs to inside these variables above.

Is that correct or is something else wrong?

* UPDATE *

CTMPESC=$(sed 's/[\*\.]/\\&/g' <<<"$CTMP")
DIRESC=$(sed 's/[\*\.]/\\&/g' <<<"$DIR")
SCRIPTESC=$(sed 's/[\*\.]/\\&/g' <<<"$SCRIPT")
crontab -l | sed "s%$CTMPESC%\*/$FREQ \* \* \* \* cd $DIRESC && \./$SCRIPTESC%" | crontab -

* UPDATE *

Here is the crontab output

*/10 * * * * cd /home/administrator/anm-1.5.0 */7 * * * * cd /home/administrator/anm-1.5.0 && ./anm.sh*/7 * * * * cd /home/administrator/anm-1.5.0 && ./anm.sh ./anm.sh

and I also echoed the three escaped variables just to troubleshoot and here they are:

\*/7 \* \* \* \* cd /home/administrator/anm-1\.5\.0 && \./anm\.sh
/home/administrator/anm-1\.5\.0
anm\.sh

The three escaped variables actually look good.

* UPDATE *

Cron file before the replace:

*/10 * * * * cd /home/administrator/anm-1.5.0 && ./anm.sh

Cron file after the replace:

*/7 * * * * cd /home/administrator/anm-1.5.0 */10 * * * * cd /home/administrator/anm-1.5.0 && ./anm.sh*/10 * * * * cd /home/administrator/anm-1.5.0 && ./anm.sh ./anm.sh

See all the extra junk that gets thrown in there somehow?

like image 878
Atomiklan Avatar asked Jun 24 '13 10:06

Atomiklan


1 Answers

Yes, the problem is likely that $CTMP contains asterisks, which are interpreted by sed as quantifiers. . is also a special character. Try escaping them:

CTMP_ESC=$(sed 's/[\*\.]/\\&/g' <<<"$CTMP")

and then use CTMP_ESC instead of CTMP.

Also, you don't need to escape / in your sed command, because you are not using it as the s/// separator.

Edit: you also need to escape & in the replacement, because sed interprets & as "the matched string". So your script should read:

CTMPESC=$(sed 's/[\*\.&]/\\&/g' <<<"$CTMP")
DIRESC=$(sed 's/[\*\.&]/\\&/g' <<<"$DIR")
SCRIPTESC=$(sed 's/[\*\.&]/\\&/g' <<<"$SCRIPT")
crontab -l | sed "s%$CTMPESC%\*/$FREQ \* \* \* \* cd $DIRESC \&\& \./$SCRIPTESC%" | crontab -
like image 52
Lev Levitsky Avatar answered Nov 15 '22 11:11

Lev Levitsky