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

时间:2016-01-14 22:59:47

标签: bash awk

我有一个文件foo,其中包含以下数据:

A<|>B<|>C<|>D
1<|>2<|>3<|>4

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

当我跑步时:

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

而不是打印

A B C D
1 2 3 4

打印

A | B | C | D 
1 | 2 | 3 | 4

背后的原因是什么?

3 个答案:

答案 0 :(得分:8)

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

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

awk 'BEGIN {FS="<\\|>"} {$1=$1}1' 

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

答案 1 :(得分:6)

Awk将您的分隔符读为正则表达式,“<>”。您必须转义管道字符(两次,看到动态正则表达式,例如字段分隔符为scanned twice):"<\\|>"

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

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

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

答案 2 :(得分:3)

顺便说一下,sed也可以在这里使用:

sed 's/<|>/ /g' file

如果您想“包含”head命令:

sed -n '1,10s/<|>/ /gp' file