我有一个名为 abc.txt 的分隔文件。它有一个标题行,其中的列名称以逗号 (,) 分隔。所有数据行和标题行使用的行分隔符是%=$%(没有换行符来表示新行)。数据行的列分隔符是|#@| 。在Unix中如何找到数据行中没有33列的行?
答案1
我不知何故无法在 Unbuntu 18 上使用 GNU Awk 4.1.4%=$%
作为记录分隔符。 Awk 宏在TXR 口齿不清作品。
打印没有33个字段的记录:
$ echo -n 'A,B,C,D%=$%FOO|#@|BAR%=$%X' | \
txr -e '(awk (:set rs #/\%=$\%/ fs ",")
((= nr 1) (set fs #/\|#@\|/) (next))
((/= nf 33) (prn)))'
FOO|#@|BAR
X
TXR Lisp 正则表达式是#/.../
并且由于%
是一个运算符( 的非贪婪版本*
),我们必须转义它。
我们可以将字段列表分配f
给自身,以(set f f)
强制rec
重新计算ofs
:
$ echo -n 'A,B,C,D%=$%FOO|#@|BAR%=$%X' | \
txr -e '(awk (:set rs #/\%=$\%/ fs ",")
((= nr 1) (set fs #/\|#@\|/) (next))
((/= nf 33) (set f f) (prn)))'
FOO BAR
X
字段是[f 0]
, [f 1]
, 整个记录是rec
:与$1
, $2
, 和不同$0
。是强制从 中的字段(set f f)
重新计算 的最短方法,就像在 Awk 中一样。rec
f
$1=$1
回到调试为什么我不能让它在 GNU Awk 中以同样的方式工作......
知道了:
$ echo -n 'A,B,C,D%=$%FOO|#@|BAR%=$%X' | gawk \
'BEGIN { RS="%=\\$%"; FS = "," }
NR == 1 { FS = "\\|#@\\|" }
NF != 33 { $1=$1; print }'
A B C D
FOO BAR
X
next
规则中缺少,NR == 1
因此我们也看到了标头。
awk 的$
正则表达式字符需要在 中转义RS
,这就是问题所在。当然,现在我已经尝试过,但错误地,并且让自己感到困惑:
# incorrect escaping of $
$ gawk -v RS='%=\$%' ''
gawk: warning: escape sequence `\$' treated as plain `$'
但我们在这里所做的是分配一个字符串,它被解释为正则表达式。 Gawk 告诉我们,\$
它的字符串文字语法中没有转义,这是正确的。不过,我们需要的是将美元符号转义为正则表达式字符。为了将其放入 Awk 字符串中,我们必须将其转义为\\
,然后转义$
正则表达式语义中的 。