【问题标题】:regex idiom for excluding word while matching other conditions用于在匹配其他条件时排除单词的正则表达式习语
【发布时间】:2014-07-31 21:49:46
【问题描述】:
问题如下。我需要匹配每一行:
- 以
<开头
- 内部没有标签
<s>
- 以标签
</s>结尾
例子:
<div> blablabla </div> blablabla </s>
<div> blablabla </div> <s> blablabla </s>
我一直在尝试放置一个否定的前瞻和一个通配符
^<((?!<s>).)*</s>$
也考虑过this trick,但目前没有成功。我也知道
grep -v
但我想要一个纯正则表达式习语,然后我可以在其他上下文中使用(如 sed)
【问题讨论】:
标签:
regex
sed
grep
negative-lookahead
【解决方案1】:
您可以使用以下正则表达式:
^(?!.*<s>)<.*</s>$
说明:
^ # the beginning of the string
(?! # look ahead to see if there is not:
.* # any character except \n (0 or more times)
<s> # '<s>'
) # end of look-ahead
< # '<'
.* # any character except \n (0 or more times)
</s> # '</s>'
$ # before an optional \n, and the end of the string
Live Demo
使用 grep,您可以使用 -P 选项,它将模式解释为 Perl 正则表达式。
grep -P '^(?!.*<s>)<.*</s>$'
您也可以考虑在上下文中使用交替运算符,将您想要排除的内容放在左侧(说扔掉它,这是垃圾)并将您想要匹配的内容放在捕获组中在右侧。
^.*<s>.*|(<.*</s>)$
Live Demo
【解决方案2】:
您提到了grep -v 方法,但想要一个“我可以在其他上下文中使用的习语(例如 sed)”。实际上,grep -v 方法也适用于sed。它还通过避免所有花哨的(通常不受支持的)正则表达式结构来保持它非常简单。实现如下:
sed -n '/<s>/n; /^<.*<\/s>/p' file
一次检查一件:
Mac OSX 笔记
如果我没记错的话,OSX sed(可能还有其他非 GNU seds)不支持与分号组合的命令。解决方法是使用-e:
sed -n -e '/<s>/n' -e '/^<.*<\/s>/p' file
【解决方案3】:
你几乎得到了答案。
^(?!.*<s>)<.*?</s>
您当前的模式所做的是搜索以< 开头的字符串,但不是紧跟<s>。而<s> 标签可以出现在您的文本中的任何位置。
【解决方案4】:
使用您评论的技巧可以帮助您。
如果你使用这个正则表达式:
.*<s>.*|(.*<\/s>)
您将在捕获组中拥有所需的行。
你有一个working example