AWK在正则表达式中使用字段值

时间:2015-02-20 02:29:51

标签: regex awk

我试图找到一个由结论一词组成的字符串模式,后跟字段$ 2的值和字段$ 5中相同记录的字段$ 3.

例如,my_file.txt由" |":

分隔
1|substance1|substance2|red|CONCLUSIONS: the effect of SUBSTANCE1 and SUBSTANCE2 in humans...|
2|substance3|substance4|red|Conclusions: Substance4 is not harmful...|
3|substance5|substance6|red|Substance5 interacts with substance6...|

所以在这个例子中我只想要打印第一条记录,因为它有"结论"然后是substance1,然后是substance2

这就是我尝试过但却无法正常工作的事情:

awk 'BEGIN{FS="|";IGNORECASE=1}{if ($5 ~ /CONCLUSIONS.*$2.*$3/) {print $0}}' my_file.txt

非常感谢任何帮助

1 个答案:

答案 0 :(得分:5)

$ awk 'BEGIN{FS="|";IGNORECASE=1} $5 ~ "conclusions.*" $2 ".*" $3' my_file.txt
1|substance1|substance2|red|CONCLUSIONS: the effect of SUBSTANCE1 and SUBSTANCE2 in humans...|

如何运作

  • BEGIN{FS="|";IGNORECASE=1}

    此部分与问题中的代码相同。

  • $5 ~ "conclusions.*" $2 ".*" $3

    这是一个条件:如果$5匹配由连接在一起的四个字符串组成的正则表达式,则为真:"conclusions.*"$2".*"和{{ 1}}。

    我们没有为此条件指定任何操作。因此,如果条件为真,$3执行默认操作即打印该行。

更简单的例子

考虑:

awk

此行不打印任何内容,因为$ echo "aa aa" | awk '$2 ~ /$1/' 不能替换正则表达式中的变量。

观察到此处未找到匹配项:

awk

这里没有匹配,因为在正则表达式中,$ echo '$1' | awk '$0 ~ /$1/' 只匹配一行的末尾。因此,$只会匹配一行后跟/$1/的结尾。如果我们想在这里得到一个匹配,我们需要逃避美元符号:

1

要获得使用awk变量的正则表达式,我们可以作为此答案的基础,执行以下操作:

$ echo '$1' | awk '$0 ~ /\$1/'
$1

这确实成功地产生了一场比赛。

进一步改进

正如Ed Morton在评论中所建议的那样,坚持认为这些物质只与整个单词相匹配可能很重要。在这种情况下,我们可以使用$ echo "aa aa" | awk '$2 ~ $1' aa aa 来限制与整个单词的实质匹配。因此:

\\<...\\>

这样,awk 'BEGIN{FS="|";IGNORECASE=1} $5 ~ "conclusions.*\\<" $2 "\\>.*\\<" $3 "\\>"' my_file.txt 将与substance1不匹配。