bash 转义sed表达式中变量中的字符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17272968/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 05:46:00  来源:igfitidea点击:

Escaping characters in variables inside sed expression

bashsed

提问by Atomiklan

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 变量只是 crontab 文件中的一行

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

The FREQvariable is the time in minutes setting of the cron file

FREQ变量是 cron 文件设置的时间(以分钟为单位)

FREQ=5

The DIR variable is the current working directory

DIR 变量是当前工作目录

DIR='/home/admin/whatever'

And the SCRIPT variable is just the script file name

而 SCRIPT 变量只是脚本文件名

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.

我觉得问题是 sed 语句没有更新 crontab 文件,因为它没有将它需要的字符转义到上面的这些变量中。

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

这是 crontab 输出

*/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:

替换前的 Cron 文件:

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

Cron file after the replace:

替换后的 Cron 文件:

*/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?

看到所有以某种方式被扔进那里的额外垃圾吗?

回答by Lev Levitsky

Yes, the problem is likely that $CTMPcontains asterisks, which are interpreted by sedas quantifiers. .is also a special character. Try escaping them:

是的,问题很可能$CTMP包含星号,这些星号被解释sed为量词。.也是一个特殊的人物。尝试逃避他们:

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

and then use CTMP_ESCinstead of CTMP.

然后使用CTMP_ESC代替CTMP

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

此外,您不需要/sed命令中转义,因为您没有使用它作为s///分隔符。

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

编辑:您还需要&在替换中转义,因为sed解释&为“匹配的字符串”。所以你的脚本应该是:

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 -