我有一个包含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)
这背后的原因是什么?
管道是正则表达式中的特殊字符,因此您需要使用反斜杠将其转义.但是这个反斜杠也是字符串文字的特殊字符,因此需要再次进行转义.所以你最终会得到以下结果:
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.简而言之,表达式被解析两次.
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也需要双重转义.