[英]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 命令行上设置
foo
和bar
,您可以在它之前导出它们,或者从配置文件或 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.