首页 > 解决方案 > awk: gsub("\\\\", "\\\\") 产生令人惊讶的结果

问题描述

考虑以下输入:

$ cat a
d:\

$ cat a.awk
{ sub("\\", "\\\\"); print $0 }

$ cat a_double.awk
{ sub("\\\\", "\\\\"); print $0 }

现在运行cat a | awk -f a.awk给出

d:\

和跑步cat a | awk -f a_double.awk

d:\\

我期望正好相反。我该如何解释这个?

$ awk -V
GNU Awk 4.1.4, API: 1.1 (GNU MPFR 4.0.1, GNU MP 6.1.2)

标签: awkescapinggsub

解决方案


是的,它的预期行为是awk. 当您sub("\\", "\\\\")在第一个脚本中运行时,在sub's 内部"(双引号)因为我们不使用/匹配模式,我们需要先转义\(实际文字字符)然后转义我们正在使用\,所以我们也需要转义它,因此它会变成\\\\

\\                                          \\
|                                            |
|                                            |
first 2 chars are denoting escaping         next 2 chars are denoting actual literal character \

您的第一种情况没有发生,因此没有匹配,因此没有替换,在您的第二个 awk 脚本中,您正在执行此操作(在 regex 匹配部分中转义部分sub),因此它\完美匹配。


让我们通过示例来看看这一点,并尝试将 put...用于检查目的。

什么都没有发生时:因为没有匹配

awk '{sub("\\", "....\\\\"); print $0}' Input_file
d:\

当模式匹配发生时:

awk '{sub("\\\\", "...\\\\"); print $0}' Input_file
d:...\\

来自man awk

gsub(r, s [, t])
For each substring matching the regular expression r in the string t,
 substitute the string s, and return the  number  of  substitutions.

我们如何才能执行实际的转义部分(我们只需要\在字符之前使用一次)?/../请在 like的第一部分中提及您的正则表达式,sub我们不需要\在这里双重转义。

awk '{sub(/\\/,"&\\")} 1' Input_file

推荐阅读