awk、gsub、& 符号和意外扩展
Awk, gsub, ampersands and unexpected expansion
首先,对于可能重复的问题表示歉意。我是 bash 脚本的新手,我什至不知道要搜索的一些关键字。话虽如此,我尽量简化问题描述:
我有一个仅包含这一行的文本文件 (test.txt):
REPLACE
我 运行 以下命令应该用代码变量值 if (A & B)
.
替换文件的文本(即 REPLACE
)
code="if (A & B)" ; awk -v var="${code}" '{ gsub(/REPLACE/, var); print }' test.txt
预期输出 我希望 code
变量值按原样打印:
if (A & B)
实际输出 以某种方式将&符号扩展为'REPLACE',即gsub
正则表达式参数:
if (A REPLACE B)
也许我需要转义符号,但不幸的是,code
变量数量超出了我的控制范围,因此我无法手动操作它的值。
仅供参考,awk 版本是 "GNU Awk 4.1.4, API: 1.1 (GNU MPFR 3.1.5, GNU MP 6.1.2)"
谢谢!
&
是许多工具中的反向引用元字符,表示 "the string that matched the regexp you searched for"。如果您尝试使用文字字符串,请使用文字字符串而不是正则表达式和反向引用。
例如:
code="if (A & B)"
awk -v old="REPLACE" -v new="$code" 's=index([=10=],old){[=10=]=substr([=10=],1,s-1) new substr([=10=],s+length(old))} 1' test.txt
尝试对正则表达式和替换进行清理的替代方法很复杂且容易出错,通常不适合胆小的人,请参阅:
您可以对“&”字符进行两次转义,这样您的代码就可以
code="if (A \\& B)" ; awk -v var="${code}" '{ gsub(/REPLACE/, var); print }' test.txt
Output:
# code="if (A \\& B)" ; awk -v var="${code}" '{ gsub(/REPLACE/, var); print }' test.txt
if (A & B)
#
请注意,在上面的示例中,您需要转义“\”和“&”字符,这就是为什么它是“\\\&”
如果您不想像上面的示例那样手动操作输入字符串,那么您可以在 awk 代码中使用额外的 'gsub' 来预处理输入字符串,以便在之前添加转义字符运行你的'gsub')如下
code="if (A & B)" ; awk -v var="${code}" '{ gsub("&","\\&", var); gsub(/REPLACE/, var); print }' test.txt
Output:
# code="if (A & B)" ; awk -v var="${code}" '{ gsub("&","\\&", var); gsub(/REPLACE/, var); print }' test.txt
if (A & B)
#
注意在预处理 gsub 中需要 4 个'\'字符。
首先,对于可能重复的问题表示歉意。我是 bash 脚本的新手,我什至不知道要搜索的一些关键字。话虽如此,我尽量简化问题描述:
我有一个仅包含这一行的文本文件 (test.txt):
REPLACE
我 运行 以下命令应该用代码变量值 if (A & B)
.
REPLACE
)
code="if (A & B)" ; awk -v var="${code}" '{ gsub(/REPLACE/, var); print }' test.txt
预期输出 我希望 code
变量值按原样打印:
if (A & B)
实际输出 以某种方式将&符号扩展为'REPLACE',即gsub
正则表达式参数:
if (A REPLACE B)
也许我需要转义符号,但不幸的是,code
变量数量超出了我的控制范围,因此我无法手动操作它的值。
仅供参考,awk 版本是 "GNU Awk 4.1.4, API: 1.1 (GNU MPFR 3.1.5, GNU MP 6.1.2)"
谢谢!
&
是许多工具中的反向引用元字符,表示 "the string that matched the regexp you searched for"。如果您尝试使用文字字符串,请使用文字字符串而不是正则表达式和反向引用。
例如:
code="if (A & B)"
awk -v old="REPLACE" -v new="$code" 's=index([=10=],old){[=10=]=substr([=10=],1,s-1) new substr([=10=],s+length(old))} 1' test.txt
尝试对正则表达式和替换进行清理的替代方法很复杂且容易出错,通常不适合胆小的人,请参阅:
您可以对“&”字符进行两次转义,这样您的代码就可以
code="if (A \\& B)" ; awk -v var="${code}" '{ gsub(/REPLACE/, var); print }' test.txt
Output:
# code="if (A \\& B)" ; awk -v var="${code}" '{ gsub(/REPLACE/, var); print }' test.txt
if (A & B)
#
请注意,在上面的示例中,您需要转义“\”和“&”字符,这就是为什么它是“\\\&”
如果您不想像上面的示例那样手动操作输入字符串,那么您可以在 awk 代码中使用额外的 'gsub' 来预处理输入字符串,以便在之前添加转义字符运行你的'gsub')如下
code="if (A & B)" ; awk -v var="${code}" '{ gsub("&","\\&", var); gsub(/REPLACE/, var); print }' test.txt
Output:
# code="if (A & B)" ; awk -v var="${code}" '{ gsub("&","\\&", var); gsub(/REPLACE/, var); print }' test.txt
if (A & B)
#
注意在预处理 gsub 中需要 4 个'\'字符。