【问题标题】:Awk, gsub, ampersands and unexpected expansionawk、gsub、& 和意外扩展
【发布时间】:2017-08-27 13:46:58
【问题描述】:

首先,对于可能重复的问题,我们深表歉意。我是 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)”

谢谢!

【问题讨论】:

  • & 表示 awk 正则表达式中的“替换完全匹配”,包括 gsub。你需要转义它:code="if (A \\& B)"(是的,有两个斜杠,因为 shell 也会进行扩展)

标签: bash shell awk gsub gawk


【解决方案1】:

& 在许多工具中是一个反向引用元字符,它的意思是“与您搜索的正则表达式匹配的字符串”。如果您尝试使用文字字符串,请使用文字字符串而不是正则表达式和反向引用。

例如:

code="if (A & B)"
awk -v old="REPLACE" -v new="$code" 's=index($0,old){$0=substr($0,1,s-1) new substr($0,s+length(old))} 1' test.txt

尝试清除正则表达式和替换的替代方法复杂且容易出错,通常不适合胆小的人,请参阅:Is it possible to escape regex metacharacters reliably with sed

【讨论】:

  • 嗨 Ed,这段代码对我帮助很大,我在使用 gsub 在 awk 中实现模板引擎时遇到了麻烦,因为 & 符号。我希望有办法禁用它。但是您的解决方案就像做梦一样。谢谢!
  • 不客气。是的,我经常希望有一个与 [g]sub() 等效的文字字符串,但是 awk 语言的一个主要观点是不为可以通过其他方式轻松完成的操作提供更简短的构造,因为这种方式是代码的恶魔膨胀,并且已经有一个不同的工具来解决这个特定的问题(参见zoitz.com/archives/13)。最后,我宁愿使用一种小型、简单的语言,也不愿使用一种大型复杂的语言,即使它确实会在这里和那里花费我一些额外的字符。
【解决方案2】:

您可以对“&”字符进行双重转义,这样您的代码就会是

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 个 '\' 字符。

【讨论】:

    猜你喜欢
    • 2012-02-22
    • 2021-12-08
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-25
    • 1970-01-01
    • 2021-11-11
    相关资源
    最近更新 更多