2016-01-14 97 views
3

我有一个文件foo具有以下数据:管道符号|在AWK字段分隔符

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 

背后有什么原因呢?

+0

只是一个提示:你可以在'awk'中使用'NR <11',而不是'head foo'。 – hek2mgl

回答

4

管道是一个正则表达式特殊字符,所以你需要用反斜杠来转义它。但是这个反斜杠也是字符串文字的一个特殊字符,所以它需要再次转义。所以,你最终的情况如下:

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

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

其原因语法如下解释相当不错:http://www.gnu.org/software/gawk/manual/gawk.html#Computed-Regexps。总之,表达式被解析两次。

+0

@EdMorton您是指原始修订版,还是由hek2mgl编辑?说实话,我只是在三个人问我后才发布答案(见其他答案的评论),但我无法删除它,因为它被接受。 – user000001

+1

做了一个编辑来澄清这一点。虽然在我看来有趣的问题。 – user000001

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也需要双重转义。

+1

可以这样写:'awk'BEGIN {FS =“<\\|>”} {$ 1 = $ 1} 1''或甚至'awk -F'<\|>''{$ 1 = $ 1} 1'' – user000001

+0

@ user000001为什么不把后者成为答案?也想回答:)但它应该是'awk -F'<\\|>''$ 1 = $ 1'' – hek2mgl

+0

我试过这个最初。取消引用|无法正常工作。它说以下内容 awk:warning:转义序列'\ |'视为普通的'|'我不太明白 – Andrew

3

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

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

如果你想“列入” head命令:

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