如何在先匹配另一个图案后打印两个图案之间的文本?

如何在先匹配另一个图案后打印两个图案之间的文本?

想象一下如下所示的一行:

Some text with MATCH1_TEXT some other text and MATCH2_TEXT until MATCH3_TEXT

我只想在包含 , 的行中搜索MATCH1_TEXT,并找到文本之间 MATCH2_TEXTMATCH3_TEXT

在上面的例子中,我想要得到until(在之前和之后都有空格字符直到)。

答案1

例如使用 sed

sed -n 's/^.*MATCH1_TEXT.*MATCH2_TEXT\(.*\)MATCH3_TEXT.*$/\1/p'

假设匹配的文本在一行中按顺序最多出现一次。

如果MATCH1_TEXT可能出现在行中的任何位置,那么查看问题的另一种方法是忽略任何没有它的行,因此程序将变为

sed -n '/MATCH1_TEXT/!d;s/.*MATCH2_TEXT\(.*\)MATCH3_TEXT.*$/\1/p'

如果MATCH2_TEXT可以发生多次,例如输入是

 text MATCH1_TEXT stuff MATCH2_TEXT and MATCH2_TEXT until MATCH3_TEXT

那么问题是需要什么输出,until或者and MATCH2_TEXT until?类似的问题也适用于 MATCH3_TEXT 的重复副本。这些可以用稍微复杂的 sed 程序来处理。例如保留最长的字符串

sed -n '/MATCH1_TEXT/!d;/MATCH2_TEXT.*MATCH3_TEXT/!d;s/MATCH2_TEXT/\n/;s/^.*\n\(.*\)MATCH3_TEXT.*$/\1/p'

其工作原理是首先拒绝任何不合适的行,然后将 MATCH2_TEXT 的第一次出现更改为换行符(该行中永远不会有换行符),然后选择换行符和 MATCH3_TEXT 之间的文本。

某些语言(例如perl和 )python已经扩展了正则表达式中可用的操作以允许“最小匹配”,这在这些情况下可能有所帮助,但不是必需的。sed它的条件循环能力比正则表达式更强大。

答案2

每当我们看到“extract”这个词时,第一个想到的应该是,grep 可以在这里帮忙吗?

在这里,我们首先 grep 出相关行,然后将它们提供给另一个 grep,然后提取在 match2 和 match3 文本之间找到的文本。这甚至会提取一行中的多个 match2/3。

$ grep MATCH1_TEXT file |\
  grep -oP '(?<=MATCH2_TEXT).*?(?=MATCH3_TEXT)' 

答案3

没有足够的示例数据来确定您的实际需求,但假设您的示例足够规范,因此

  1. MATCH1_TEXTMATCH2_TEXT、 和MATCH3_TEXT都在一行上
  2. MATCH1_TEXT总是先于MATCH2_TEXT
  3. MATCHn_TEXT可能会匹配里面THEMATCHn_TEXTS

perl然后,您可以使用或 GNU的单次调用grep来提取所需的数据

grep -oP 'MATCH1_TEXT.*?MATCH2_TEXT\K.*?(?=MATCH3_TEXT)'

对于您的示例数据行,输出为until(带有一个前导和尾随空格)。

相关内容