本问题已经有最佳答案,请猛点这里访问。
我正在尝试用另一个命令的输出替换文件中的文本。 不幸的是,输出的文本包含bash扩展字符。 例如,我正在运行以下脚本来更改文件(somestring引用输出会破坏sed命令):
#!/bin/bash
somestring='$6$sPnfj/lnXwZVrec7$fCnL9uy1oWIMZduInKTHBAxhsQxGCsBpm2XfVFFqDPHKidrd93yfjbYvKgYexXHVcvkKdu9lbfy16Ek5GvKy/1'
sed '0,/^title/s/^title*/'"$somestring"'
&/' $HOME/example.txt
sed失败,并显示以下错误:
sed: -e expression #1, char 30: unknown option to `s'
我认为bash在构建sed命令时正在替换$ somestring的内容,但是随后尝试扩展结果文本。 我不能将整个sed脚本放在单引号中,我需要bash第一次对其进行扩展,而无需第二次对其进行扩展。 有什么建议么? 谢谢
somestring=$6$sPnfjlnXwZVrec7$fCnL9uy1oWIMZduInKTHBAxhsQxGCsBpm2XfVFFqDPHKidrd93yfjbYvKgYexXHVcvkKdu9lbfy16Ek5GvKy1真的是您能想到的最简短的例子来重现该问题吗? 无论如何....您可能正在尝试使用错误的工具,但是如果您卡在sed上,请参阅stackoverflow.com/q/29613304/1745001。
这里是正斜杠/的问题。如果这是唯一的问题,则可以将sed设置为使用其他定界符。
例如
$ somestring="abc/def"; echo xxx | sed 's/xxx/'"$somestring"'/'
sed: -e expression #1, char 11: unknown option to `s'
$ somestring="abc/def"; echo xxx | sed 's_xxx_'"$somestring"'_'
abc/def
您还需要担心&和\字符,如果可以出现在替换文本中,请对其进行转义。
如果无法控制替换字符串,则必须使用另一个sed脚本进行清理,或者使用r命令从文件中读取它。例如,
$ seq 5 | sed -e '/3/{r replace' -e 'd}'
1
2
3slashes///1ampersand&and2backslashes\\end
4
5
哪里
$ cat replace
3slashes///1ampersand&and2backslashes\\end
谢谢,我还没有意识到您用sed更改了定界符。 somestring变量保存名为grub-crypt的命令的输出。 它在运行时生成,我如何转义整个字符串,我不知道会出现什么文本。
如果您的外壳是Bash,则可以使用参数替换来替换有问题的/:
somestring="{somestring//\//\\/}"
这看起来很吓人,但是如果您查看将x替换为__的版本,则更容易理解:
somestring="${somestring//x/__}"
使用(例如)下划线作为sed s命令的定界符可能会更容易,然后上面的替换将是
somestring="${somestring//_/\\_}"
如果已经有反斜杠,则需要先替换它们:
somestring="${somestring//\\/\\\\}"
somestring="{somestring//\//\\/}"
如果还有其他需要转义的字符(例如在s///的搜索侧),则可以适当地扩展上述内容。
您在这里有几个错误:
字符串somestring具有对sed命令有意义的字符(最重要的是您用作定界符的'/'),可以通过将其替换为前一个字符来对其进行转义
<5233>
会将您的/字符转换为\/序列。
您使用的是sed '0,/^title/s/^title*/'"$somestring"'
&/' $HOME/example.txt,它试图用该$somestring值替换字符串titl,后跟任意数量的e字符,后跟新行和原始行。不幸的是,sed(1)不允许您在s命令的模式替换侧使用换行符,但是您可以通过使用i命令以及由模式组成的文本来负担结果(在任何新字符之前用\行将其解释为文字):
最后,脚本导致:
#!/bin/bash
somestring='$6$sPnfj/lnXwZVrec7$fCnL9uy1oWIMZduInKTHBAxhsQxGCsBpm2XfVFFqDPHKidrd93yfjbYvKgYexXHVcvkKdu9lbfy16Ek5GvKy/1'
somestring=$(echo"$somestring" | sed -e 's/\//\\\//g')
sed '/^title/i\
'"$somestring\\" $HOME/example.txt
此URL提供最干净的答案:
在bash中转义字符串的命令
printf"%q""$someVariable"
将转义您需要转义的所有字符。
不幸的是,所需的转义不是bash(1),而是sed(1)命令。