sed:在所有出现的情况中匹配两个不同的连续匹配之间的字符串

sed:在所有出现的情况中匹配两个不同的连续匹配之间的字符串

我有:

bananaOPENqwertyCLOSErandomtextOPENgrapesCLOSEwhateverOPENsunshineCLOSEgreymoon

这一行可能包含更多 OPEN 和 CLOSE 字符串。

我想打印整行,仅包含任何连续的 OPEN 和 CLOSE 之间的内容,并丢弃其他内容。即我想要这样的输出:

qwertygrapessunshine

我能想到的最接近的答案是: sed -n 's/OPEN\(.*\)CLOSE/\1/g;p' 这显然不起作用。

答案1

因为sed匹配是“贪婪的”(更准确地说,最左边最长),所以这很棘手。尝试:

$ sed 's/OPEN/\n/g; s/[^\n]*\n//; s/CLOSE[^\n]*\n//g; s/CLOSE.*$//' file
qwertygrapessunshine

以上内容已在 GNU 上测试sed。如果您使用的是 BSD/MacOS,则可能需要进行一些细微但烦人的更改。

怎么运行的

请记住,默认情况下,sed 每次将一行读入其模式空间。这意味着,当我们开始处理模式空间时,它永远不会包含换行符。因此,我们可以使用换行符\n作为标记,而不会产生歧义。

  • s/OPEN/\n/g

    OPEN用换行符替换

    默认情况下,sed每次只将一行读入其模式空间。这意味着模式空间本身永远不会包含换行符。

  • s/[^\n]*\n//

    删除第一个OPEN(现在是换行符)之前的所有内容。

    请注意,[\n]*匹配零个或多个除换行符之外的任何字符。因此,[^\n]*\n匹配零个或多个除换行符后跟换行符之外的任何字符。这意味着它匹配至并包括下一个换行符。相比之下,由于 sed 表达式是“贪婪的”(最左边最长),因此.*\n匹配直到并包括最后的模式空间中的换行符。

  • s/CLOSE[^\n]*\n//g

    删除从下CLOSE一个换行符开始到下一个换行符的所有内容。

  • s/CLOSE.*$//

    从最后一个字符删除CLOSE到行末字符。

相关内容