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 没有指定\c
当c
不是"
, /
,\ddd
之一且d
是八进制数字 , \
, a
, b
, f
, n
, r
, t
,时的行为v
。因此您不知道字符串是否\c
会作为 ERE 传递\c
或传递c
给 ERE。
gawk
,nawk
, 和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