为什么我无法在gawk中转义引号?

3
我正在尝试以下操作,但要么是我太累了无法思考,要么是转义出现了问题:
scanimage -L | gawk '/N650U/ {print gensub("[\'`]", "", "g", $2)}'
pipe bquote> 
5个回答

7
创建一个包含单引号的变量,然后使用该变量即可完成此操作。中文谚语是:“工欲善其事,必先利其器”。
scanimage -L | gawk '/N650U/ {print gensub(q"`", "", "g", $2)}' q="'"

然而,由于你在字符类中使用了它,这样是行不通的,所以你需要这样做:

scanimage -L | gawk '/N650U/ {print gensub("[`'\'']", "", "g", $2)}'
                    <--      1st pair       -->  <--   2nd pair  -->

如果使用 bash 的话,另一种选择是使用 $'',它支持转义单引号。

scanimage -L | gawk $'/N650U/ {print gensub("[`\']", "", "g", $2)}'

在第二种情况下,你所做的就是在你的单引号文字前创建一个单引号对,转义单引号,这样 shell 就不会解释它,然后在它之后再做一次单引号对。

在正则表达式中使用单引号的示例

$ echo $'foo`\'' | awk '{gsub(/[o`'\'']/,"#")}1'
f####

单引号在正则表达式外的示例

$ echo "foo" | awk '{print q$0q}' q="'"
'foo'

使用单引号的示例 $''

echo $'foo`\'' | awk $'{gsub(/[o`\']/,"#")}1'
f####

1
那第一行不起作用,因为你把q放在双引号里面:你需要 gensub(q"\", ""... - David Given
不要使用单引号,而是使用\047。当您使用变量时,您强制awk使用字符串文字而不是正则表达式文字,因此强制自己对所有内容进行双重转义(请参阅man页面或Google)。只需使用foo\047bar表示foo'bar并避免所有麻烦。请注意,这仅适用于单引号分隔的脚本,如果您的脚本存储在文件中并作为awk -f script调用,则可以直接使用字面单引号。 - Ed Morton
@EdMorton 我认为争论什么是习语,什么不是习语,我们不会取得太多进展,因为这是非常主观的。虽然我感谢您的评论,但如果我不关心极端可移植性,我更喜欢使用$''而不是\ 047 - SiegeX
除了允许您在脚本中嵌入单引号之外,$'' 有什么其他作用吗?我觉得它不可能只有这一个作用,但是确切的作用还需要进一步确认。 - Ed Morton

2

单引号中没有特殊字符,包括反斜杠(\)。

用单引号(')包围字符可以保留引号内每个字符的字面值。即使在单引号前加反斜线,单引号也不能出现在单引号之间。

您可以将命令更改为:

$ scanimage -L | awk '/N650U/ {print gensub("['"'"'`]", "", "g", $2)}'

谢谢,这正是我在寻找的。您能简要解释一下正则表达式 ['"'"'] 中 字符的作用吗? - RonnyKnoxville
1
@JackalopeZero 给命令添加额外的空格:'...' "..." '...'。很简单:将三个字符串连接在一起。 - kev
1
你需要删除空格来连接。这样很难阅读。但很容易理解。 - kev

1

Shell '...' 不支持反斜杠转义。恐怕你必须使用 "..." 代替。

gawk "/N650U/ {print gensub(\"['`]\", \"\", \"g\", \$2)}\"

(请注意,shell中的“...”确实会扩展$变量,因此您也需要对其进行转义!)


1
更容易的方法是只转义单引号。 - SiegeX
说实话,在这种引号和反斜杠交织的可怕迷宫中保持清醒的唯一方法就是将gawk脚本放在自己的文件中。 - David Given

0
gawk '/N650U/ {print gensub("[\'`]", "", "g", $2)}'
     ^                         ^
     beginning of sq string       end of single quoted string

有点丑,但这个可以工作:

gawk '/N650U/ {print gensub("['"'"'`]", "", "g", $2)}'

不是用双引号,而是转义它。这样会有些丑陋,但不会丑陋。 - SiegeX
没错,这样少了一个字符,但我也认为使用 "['\'']" 显得更容易看出单引号被使用了,要比 "['"'"']" 好一些。或许只有我这么想,不确定。 - SiegeX

0

正确的做法很简单:

scanimage -L | gawk '/N650U/ {print gensub(/[\047`]/, "", "g", $2)}'

这不会影响使用\047表示单引号,但是请注意,所有其他发布的解决方案都使用字符串分隔符,而不是围绕gsub()的第一个参数的正则表达式分隔符。 这很重要,请参见以下示例:

$ printf 'a\\tb\n' | awk '{sub(/\\t/,"X")}1'
aXb
$ printf 'a\\tb\n' | awk '{sub("\\t","X")}1'
a\tb
$ printf 'a\\tb\n' | awk '{sub("\\\\t","X")}1'
aXb

在正则表达式上下文中使用字符串分隔符的唯一时机是当您需要将文字与变量连接起来时,例如:
awk '{sub("<"var">","")}1'

请在手册中查找字符串和正则表达式定界符的详细信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接