我有一个文件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
背后的原因是什么?
答案 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