想象一下如下所示的一行:
Some text with MATCH1_TEXT some other text and MATCH2_TEXT until MATCH3_TEXT
我只想在包含 , 的行中搜索MATCH1_TEXT
,并找到文本之间 MATCH2_TEXT
和MATCH3_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
没有足够的示例数据来确定您的实际需求,但假设您的示例足够规范,因此
MATCH1_TEXT
、MATCH2_TEXT
、 和MATCH3_TEXT
都在一行上MATCH1_TEXT
总是先于MATCH2_TEXT
MATCHn_TEXT
可能会匹配里面THEMATCHn_TEXTS
perl
然后,您可以使用或 GNU的单次调用grep
来提取所需的数据
grep -oP 'MATCH1_TEXT.*?MATCH2_TEXT\K.*?(?=MATCH3_TEXT)'
对于您的示例数据行,输出为until
(带有一个前导和尾随空格)。