简体   繁体   English

使用 sed 替换为带有特殊字符的 var

[英]Using sed to replace to a var with special characters

I want to replace a placeholder on a file <<string>> in the example to the contents of a var that has several special characters.我想将示例中文件<<string>>上的占位符替换为具有多个特殊字符的 var 的内容。

file.txt文件.txt

My string: <<string>>

script.sh脚本文件

STRING="something-else;device=name.of.device;key=abcd1234/wtp="
sed -i "s/<<string>>/${STRING}/g" file.txt

I get this error:我收到此错误:

sed: -e expression #1, char 165: unknown option to `s'

I already use this sed command for other vars that do not have special characters.我已经将此sed命令用于其他没有特殊字符的变量。 Any way to escape the var ${STRING} entirely?有什么办法可以完全转义 var ${STRING} 吗?

You can't do this job easily and robustly with sed, see Is it possible to escape regex metacharacters reliably with sed .您无法使用 sed 轻松而稳健地完成这项工作,请参阅是否可以使用 sed 可靠地转义正则表达式元字符 Instead just use a tool like awk that understands literal strings:相反,只需使用像 awk 这样理解文字字符串的工具:

$ string='~`!@#$%^&*()-_+={[}]|\:;"'\''<,>.?/\1'

$ echo "$string"
~`!@#$%^&*()-_+={[}]|\:;"'<,>.?/\1

$ string="$string" awk -i inplace 'match($0,/(.*)(<<string>>)(.*)/,a){ $0=a[1] ENVIRON["string"] a[3] } 1' file.txt

$ cat file.txt
My string: ~`!@#$%^&*()-_+={[}]|\:;"'<,>.?/\1

That above will work for any characters (or backreference substrings like \\1 ) that string might contain because it's simply using a literal string operation (concatenation) for the replacement.上面的内容适用于string可能包含的任何字符(或反向引用子字符串,如\\1 ),因为它只是使用文字字符串操作(连接)进行替换。

It's using GNU awk for -i inplace just the same as your original script used GNU sed for -i .它使用 GNU awk for -i inplace就像你的原始脚本使用 GNU sed for -i

Don't use all upper case for non-exported variable names by the way to avoid clashes with exported and built-in variables and not obfuscate your code by making it look like you're using exported variables, see Correct Bash and shell script variable capitalization .顺便说一下,不要对非导出变量名称使用全部大写,以避免与导出和内置变量发生冲突,并且不要通过使代码看起来像是在使用导出变量来混淆代码,请参阅更正 Bash 和 shell 脚本变量大写

Note that if you have multiple <<whatever>> placeholders you can easily parameterize the above, eg:请注意,如果您有多个<<whatever>>占位符,您可以轻松地参数化上述内容,例如:

$ foo='Now is the Winter'
$ bar='Of our discontent'

$ cat file.txt
My foo string: <<foo>>
My bar string: <<bar>>

$ foo="$foo" bar="$bar" awk -i inplace 'match($0,/(.*)<<(\w+)>>(.*)/,a) && (a[2] in ENVIRON){ $0=a[1] ENVIRON[a[2]] a[3] } 1' file.txt

$ cat file.txt
My foo string: Now is the Winter
My bar string: Of our discontent

If you don't want to set foo and bar on the awk command line you can export them before it, or read them from a config file or a here-doc or ... - lots of options.如果您不想在 awk 命令行上设置foobar ,您可以在它之前导出它们,或者从配置文件或 here-doc 或 ... - 很多选项中读取它们。

Since STRING contains a / , you should use a other delimiter, for example, you can use ^ like so:由于STRING包含/ ,您应该使用其他分隔符,例如,您可以像这样使用^

sed  's^<<string>>^'"$STRING"'^g' file.txt

The quoting logic ( ''""'' ) is explained nicely on this SO answer .引用逻辑( ''""''在这个 SO answer 上得到了很好的解释。


Example on my locale machine:我的语言环境机器上的示例:

$
$ cat file.txt
My string: <<string>>
$
$
$ STRING="something-else;device=name.of.device;key=abcd1234/wtp="
$
$
$ sed -i 's^<<string>>^'"$STRING"'^g' file.txt
$
$ cat file.txt
My string: something-else;device=name.of.device;key=abcd1234/wtp=
$
$

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM