如果行分隔符是%=$%(没有\n字符)并且列分隔符是|#@|如何在 Unix 中查找具有不同数量的列分隔符的行?

如果行分隔符是%=$%(没有\n字符)并且列分隔符是|#@|如何在 Unix 中查找具有不同数量的列分隔符的行?

我有一个名为 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 中一样。recf$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 字符串中,我们必须将其转义为\\,然后转义$正则表达式语义中的 。

相关内容