正则表达式用于在匹配其他条件时排除单词

时间:2014-07-31 21:49:47

标签: regex sed grep negative-lookahead

问题如下。我需要匹配每一行:

  • <
  • 开头
  • 内部没有标记<s>
  • 以标记</s>
  • 结尾

示例:

<div> blablabla </div> blablabla </s>
<div> blablabla </div> <s> blablabla </s>

我一直试图通过放置一个负向前瞻和一个通配符

^<((?!<s>).)*</s>$

并且还考虑了this trick,但到目前为止还没有成功。我也知道

grep -v

但是我希望有一个纯正的正则表达式,然后我可以在其他环境中使用(比如sed)

4 个答案:

答案 0 :(得分:2)

您可以使用以下正则表达式:

^(?!.*<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

答案 1 :(得分:1)

你几乎已经达到了答案。

^(?!.*<s>)<.*?</s>

您当前的模式所做的是搜索以<开头的字符串,但不会紧跟<s>。然而,<s>标记可以出现在您的文本中的任何位置。

答案 2 :(得分:1)

你提到grep -v方法,但想要一个“我可以在其他环境中使用的习语(比如sed)。”实际上,grep -v方法也适用于sed。它还通过避免所有花哨(通常不受支持)的正则表达式构造来保持它非常简单。它实现如下:

sed -n '/<s>/n; /^<.*<\/s>/p' file

一次检查一件:

  • -n

    除非明确询问,否则告诉sed不要打印任何内容。

  • /<s>/n;

    这会告诉sed跳过<s>的任何一行。此命令与grep -v类似。 (在sed中,n命令意味着跳到下一行。)

  • /^<.*<\/s>/p

    这将选择您想要的行并打印它们。

Mac OSX Note

如果我没记错的话,OSX sed(可能还有其他非GNU seds)不支持带分号的命令。解决方法是使用-e

sed -n -e '/<s>/n' -e '/^<.*<\/s>/p' file

答案 3 :(得分:0)

使用您评论的技巧可以帮助您。

如果你使用这个正则表达式:

.*<s>.*|(.*<\/s>)

您将在捕获组中拥有所需的行。

您有一个 working example

enter image description here