管道符号| 在AWK字段分隔符中

And*_*rew 7 bash awk

我有一个包含foo以下数据的文件:

A<|>B<|>C<|>D
1<|>2<|>3<|>4
Run Code Online (Sandbox Code Playgroud)

我想使用awk正确访问每一列,但它没有正确解释字段分隔符.

当我跑:

head foo | \
  awk 'BEGIN {FS="<|>"} {out=""; for(i=1;i<=NF;i++){out=out" "$i}; print out}'
Run Code Online (Sandbox Code Playgroud)

而不是打印

A B C D
1 2 3 4
Run Code Online (Sandbox Code Playgroud)

它打印

A | B | C | D 
1 | 2 | 3 | 4
Run Code Online (Sandbox Code Playgroud)

这背后的原因是什么?

use*_*001 8

管道是正则表达式中的特殊字符,因此您需要使用反斜杠将其转义.但是这个反斜杠也是字符串文字的特殊字符,因此需要再次进行转义.所以你最终会得到以下结果:

awk -F '<\\|>' '{$1=$1}1'

awk 'BEGIN {FS="<\\|>"} {$1=$1}1' 
Run Code Online (Sandbox Code Playgroud)

这里解释了这种语法的原因:http://www.gnu.org/software/gawk/manual/gawk.html#Computed-Regexps.简而言之,表达式被解析两次.


Ben*_* W. 6

Awk将您的分隔符读作正则表达式" <>".你必须逃脱管道符(两次,看到动态的正则表达式,如字段分隔符是扫描两次)"<\\|>".

您还可以将字段分隔符指定为参数:

awk -F '<\\|>' '{out=""; for(i=1;i<=NF;i++){out=out" "$i}; print out}' <<< 'A<|>B<|>C<|>D'
 A B C D
Run Code Online (Sandbox Code Playgroud)

根据您的awk版本,您可能只需单次转义即可逃脱.对我来说,mawk 1.3.3适用于两者-F '<\|>'-F '<\\|>',并且gawk 4.0.1需要-F '<\\|>'.我不完全确定POSIX awk走哪条路,但是在--posix模式下运行gawk也需要双重转义.

  • @ user000001公平点.但是你仍然需要`-F'<\\ |>'`而不是`-F'<\ |>'` (2认同)