具有正则表达式前瞻或后瞻的awk字段分隔符

时间:2015-05-25 02:34:48

标签: regex awk

我想用转义序列拆分但是失败了。例如:

$ echo "1,2\,2,333"|awk -F "(?<\!\\,)," '{print $2}'   ## expecting "2\,2"
awk: warning: escape sequence `\!' treated as plain `!'
awk: warning: escape sequence `\,' treated as plain `,'

awk / gawk是否支持带regexp lookahead或lookbehind的字段分隔符?

2 个答案:

答案 0 :(得分:4)

正如我在评论中所说,awk不支持前瞻或后视,因为它使用POSIX扩展正则表达式(ERE)。如果你真的需要前瞻或后瞻,你可能想要使用Perl。但是,在这种情况下,您可以稍微改变解决问题的方法。

如果数据包含分隔符,而不是通过查找未转义的分隔符来拆分数据(当行中有许多\时可能会失败),最好直接匹配字段。

匹配字段的正则表达式为/([^\\,]|\\.)+/。请注意,此正则表达式不知道引用的字段。如果您想支持它们,则取决于您如何处理报价未正确关闭的情况,或者字段中有多个引号。如果您可以假设您的数据格式正确,那么您可以想出一个适用于您的数据的正则表达式。

这是让你入门的东西。下面的代码打印一行中的所有字段。

echo "1,2\,2,333" | awk '{while (match($0, /([^\\,]|\\.)+/)) {print substr($0, RSTART, RLENGTH);$0=substr($0, RSTART+RLENGTH)}}'

参考

答案 1 :(得分:3)

处理此问题的一种方法是gnu-awk中的using FPAT (splitting by content)

awk 'BEGIN{ FPAT=",([^\\\\]*\\\\,)*[^,]*,|[^,]+" } {
  for (i=1; i<=NF; i++) {gsub(/^,|,$/, "", $i); printf "$%d: <%s>\n", i, $i}
}' <<< "1,2\,2,333"
$1: <1>
$2: <2\,2>
$3: <333>