sed - 在第一次出现MATCH1和下次出现MATCH2之间提取STRING

时间:2010-12-08 20:43:02

标签: regex bash sed

使用sed,我想在第一次出现MATCH1和下次出现MATCH2之间提取STRING。

echo "abcd MATCH1 STRING MATCH2 efgh MATCH1 ijk MATCH2 MATCH2 lmnop MATCH1" | sed...

我以各种方式尝试了这一点,但鉴于MATCH1MATCH2两者可能连续出现多次,因此很难提取STRING。知道我怎么能达到这个结果吗?

4 个答案:

答案 0 :(得分:3)

您可以使用非贪婪的正则表达式匹配来执行perl:

echo "abcd MATCH1 STRING MATCH2 efgh MATCH1 ijk MATCH2 MATCH2 lmnop MATCH1" | perl -pe 's|^.*?MATCH1(.*?)MATCH2.*$|\1|'

sed不支持这些。

编辑:这是一个将Dennis的解决方案与sed结合起来的解决方案:

echo "abcd MATCH1 STRING MATCH2 efgh MATCH1 ijk MATCH2 MATCH2 lmnop MATCH1" | grep -Po '^.*?MATCH1.*?MATCH2' | sed 's/^.*MATCH1\(.*\)MATCH2$/\1/'

答案 1 :(得分:3)

这些只会在匹配项之间返回字符串,即使MATCH1 == MATCH2也可以正常工作。

echo ... | grep -Po '^.*?\K(?<=MATCH1).*?(?=MATCH2)'

这是一个sed解决方案:

echo ... | sed  's/MATCH1/&\n/;s/.*\n//;s/MATCH2/\n&/;s/\n.*//'

与其他一些解决方案相比,这些解决方案的优点是每个解决方案只包含一次对单个实用程序的调用。

答案 2 :(得分:2)

您可以通过两次调用sed来执行此操作,首先用新行替换空格,然后将该输出汇总到另一个sed实例,删除其他所有内容。

sed 's/ /\n/g' | sed '1,/MATCH1/d;/MATCH2/,$d'


修改

如果第一行(替换后)恰好是MATCH1,那么gnu sed可以使用0,/MATCH1/代替1,/MATCH1/来解决这个问题:

sed 's/ /\n/g' | sed '0,/MATCH1/d;/MATCH2/,$d'

EDIT2

sed解决方案的单次调用的优化版本,只需要3次替换,而不是4次

sed -r 's/MATCH1/&\n/;s/MATCH2/\n&/;s/^.*\n(.*)\n.*$/\1/'

答案 3 :(得分:0)

这可能对您有用:

echo "abcd MATCH1 STRING MATCH2 efgh MATCH1 ijk MATCH2 MATCH2 lmnop MATCH1" | 
sed 's/MATCH1/\n&/;s/[^\n]*\n//;s/\(MATCH2\).*/\1/'
MATCH1 STRING MATCH2