带有反斜杠的 awk FS

带有反斜杠的 awk FS

find . -maxdepth 1 -not -type d 我使用生成输出的命令,例如./filename.1.out

我将 find 命令输出通过管道传输到awk.目标是在文字./或上进行拆分.。我让它工作使用:

find . -maxdepth 1 -not -type d | gawk 'BEGIN { FS = "(\\./)|(\\.)" } ; { print NF }'

事实上,如果我在第一组括号中删除第一个反斜杠,它就会起作用。前任:

find . -maxdepth 1 -not -type d | gawk 'BEGIN { FS = "(\./)|(\\.)" } ; { print NF }'

我不明白 - 我的问题是为什么如果我使用它不起作用:

find . -maxdepth 1 -not -type d | gawk 'BEGIN { FS = "(\./)|(\.)" } ; { print NF }'

我所说的“不起作用”是指 NF 返回一个数字,就好像第二个 paren 是 regex 一样。字符(匹配任何类型的字符)。也许我正在回答我自己的问题......但是当我查看命令/行为时,似乎最初的反斜杠被忽略了。事实上,有一条警告转义序列消息说\。被视为普通的“.”。但直到我开始打印 NF 之前我才真正明白它在做什么。

事实上...转义序列的 awk 文档 (https://www.gnu.org/software/gawk/manual/html_node/Escape-Sequences.html#Escape-Sequences) 说:

反斜杠字符本身是另一个不能正常包含的字符;您必须\\在字符串或正则表达式中写入一个反斜杠。

因此,如果我想编写正则表达式来匹配美元符号,那么我需要FS="\\$"?

发这个帖子的初衷是想问一下为什么会出现这种情况。然后我相信我可能已经把事情拼凑起来了。如果我错了,请纠正我。

答案1

FS值被扫描两次,第一次作为字符串值,第二次作为 ERE(请参阅词汇约定)。

而且,POSIX 没有指定\cc不是", /,\ddd之一且d是八进制数字 , \, a, b, f, n, r, t,时的行为v。因此您不知道字符串是否\c会作为 ERE 传递\c或传递c给 ERE。

gawknawk, 和Brian Kernighan 自己的版本给你c,同时mawk给你\c

$ for AWK in gawk mawk nawk bk-awk; do
  printf '<%s>\n' "$AWK"
  echo | "$AWK" -F '\.' '{print FS}'
done
<gawk>
gawk: warning: escape sequence `\.' treated as plain `.'
.
<mawk>
\.
<nawk>
.
<bk-awk>
.

因为\\将始终被识别为\,那么您将安全\\c

$ for AWK in gawk mawk nawk bk-awk; do
printf '<%s>\n' "$AWK"; echo | "$AWK" -F '\\.' '{print FS}'
done
<gawk>
\.
<mawk>
\.
<nawk>
\.
<bk-awk>
\.

的字符串值\\c将为\c,因此将其用作 ERE 将为您提供所需的结果。

答案2

\x在被视为正则表达式之前,它会成为双引号字符串中的一个字符(就像在大多数 shell 和 C 中一样),因此您确实需要键入\\.来构造\..

让我们测试一下(您不需要括号,因为交替运算符|的优先级最低):

$ echo ./a.b.c | gawk 'BEGIN { FS = "\.|\./" } { for (i=1; i<=NF; i++) { print i ": " $i } }'
gawk: cmd. line:1: warning: escape sequence `\.' treated as plain `.'
1: 
2: 
3: 
4: 
5: 
6: 
7: 

该警告告诉您字符串中的转义序列是多余的。所以 FS 就是这样.|./,你对每个字符进行分割,产生一堆空字段。

现在加倍\

$ echo ./a.b.c | gawk 'BEGIN { FS = "\\.|\\./" } { for (i=1; i<=NF; i++) { print i ": " $i } }'
1: 
2: a
3: b
4: c

相关内容