我有:
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
到行末字符。