正则表达式匹配不包含单词的行?

knaser 4121 regex regex-negation

我知道可以匹配一个单词,然后使用其他工具(例如grep -v)反转匹配.但是,我想知道是否可以使用正则表达式匹配包含特定单词的行(例如hede).

输入:

hoho
hihi
haha
hede

码:

grep "<Regex for 'doesn't contain hede'>" input

期望的输出:

hoho
hihi
haha

Bart Kiers.. 5622

正则表达式不支持逆匹配的概念并不完全正确.您可以使用负面外观来模仿此行为:

^((?!hede).)*$

上面的正则表达式将匹配任何字符串,或没有换行符的行,包含(子)字符串'hede'.如上所述,这不是正则表达式(或应该做的)"好"的东西,但仍然可能的.

如果您还需要匹配换行符,请使用DOT-ALL修饰符(s以下模式中的尾部):

/^((?!hede).)*$/s

或者内联使用:

/(?s)^((?!hede).)*$/

(/.../正则表达式是正则表达式分隔符,即不是模式的一部分)

如果DOT-ALL修饰符不可用,则可以使用字符类模仿相同的行为[\s\S]:

/^((?!hede)[\s\S])*$/

说明

字符串只是一个n字符列表.在每个字符之前和之后,都有一个空字符串.因此,n字符列表将具有n+1空字符串.考虑字符串"ABhedeCD":

    ????????????????????????????????????????????????????????????
S = ?e1? A ?e2? B ?e3? h ?e4? e ?e5? d ?e6? e ?e7? C ?e8? D ?e9?
    ????????????????????????????????????????????????????????????

index    0      1      2      3      4      5      6      7

其中e的是空字符串.正则表达式(?!hede).向前看是否没有要查看的子字符串"hede",如果是这种情况(所以看到别的东西),那么.(点)将匹配除换行符之外的任何字符.环视也称为零宽度断言,因为它们不消耗任何字符.他们只断言/验证某些东西.

因此,在我的示例中,首先验证每个空字符串,以查看"hede".(点)消耗字符之前是否没有提前.正则表达式(?!hede).只会执行一次,所以它被包装在一个组中,并重复零次或多次:((?!hede).)*.最后,锚定输入的开始和结束以确保消耗整个输入:^((?!hede).)*$

正如你所看到的,输入"ABhedeCD"将失败,因为上e3,正则表达式(?!hede)失败(也就是 "hede"向上前进!).

  • @PeterK,当然,但这是SO,而不是MathOverflow或CS-Stackexchange.在这里提问的人通常都在寻找一个实际的答案.大多数具有正则表达式支持的库或工具(如OP提到的`grep`)都具有在理论意义上使它们非常规的特征. (45认同)
  • 我不会说这是正则表达式不好的地方.这种解决方案的便利性非常明显,与程序化搜索相比,性能上的提升通常并不重要. (23认同)
  • 严格来说,负面的低头向前使你的正则表达不规律. (23认同)
  • @Bart Kiers,没有冒犯你的回答,只是这种滥用术语让我有点恼火.这里真正令人困惑的部分是严格意义上的正则表达式可以非常符合OP的要求,但是编写它们的通用语言不允许它,这会导致(数学上丑陋)变通方法,如前瞻.请参阅下面的[此答案](http://stackoverflow.com/questions/406230/regular-expression-to-match-line-that-doesnt-contain-a-word/31825535#31825535)和我的评论(理论上对齐)正确的做法.不用说它在大输入上运行得更快. (18认同)
  • 如果您想知道如何在vim中执行此操作:`^ \(\(hede \)\ @!.\)*$` (16认同)
  • @ Z.Khullah你错过了`m`标志.在你的正则表达式中添加它并不能解决问题,但使用`m`创建一个新的测试确实可以在Regexr上运行:https://regexr.com/3hj1b简而言之:它是Regexr中的一个错误. (3认同)
  • 为什么这么多答案说`^((?! hede)。)* $`?使用`^(?!。* hede)。* $`不是更有效吗?它执行相同的操作,但步骤更少。 (3认同)

JoshuaDavid.. 710

请注意,解决方案 "hede" 开头:

^(?!hede).*$

通常比包含 "hede"的解决方案更有效:

^((?!hede).)*$

前者仅在输入字符串的第一个位置而不是在每个位置检查"hede".

  • 谢谢,我用它来验证字符串dos不包含数字的序列^((?!\ d {5,}).)* (5认同)
  • 为什么这么多答案说`^((?! hede)。)* $`?使用`^(?!。* hede)。* $`不是更有效吗?它做同样的事情,但步骤更少 (3认同)
  • 你好!我无法撰写**不会_end_与"hede"**正则表达式.你能帮忙吗? (2认同)

Athena.. 199

如果您只是将它用于grep,则可以使用grep -v hede获取所有不包含hede的行.

ETA哦,重读这个问题,grep -v可能就是你所说的"工具选项".

  • 或者只使用一个过程`grep -v -e hede -e hihi -e ...` (48认同)
  • 提示:逐步过滤掉你不想要的东西:grep -v"hede"| grep -v"hihi"| ...等等. (20认同)
  • 或者只是`grep -v"hede\| hihi"`:) (13认同)
  • 或简单地使用`egrep`或`grep -Ev“ hede | hihi | etc”`以避免尴尬的转义。 (3认同)
  • 如果您有很多要过滤的模式,请将它们放在文件中并使用`grep -vf pattern_file file`。 (2认同)

Jessica.. 150

回答:

^((?!hede).)*$

说明:

^字符串的开头, (组和捕获到\ 1(0次或更多次(匹配尽可能多的数量)),
(?!展望未来,看看是否有,

hede 你的字符串,

)结束前瞻, .除了\n之外的任何字符
)*,\ 1结束(注意:因为你在这个捕获中使用量词,只有最后重复捕获的模式将存储在\ 1中)
$才能选择\n,和字符串的结尾

  • 使用多个单词'^((?!DSAU_PW8882WEB2 | DSAU_PW8884WEB2 | DSAU_PW8884WEB)在sublime text 2中为我工作的真棒.)*$`' (13认同)
  • @DamodarBashyal我知道我已经很晚了,但你可以完全删除那里的第二个词,你会得到完全相同的结果 (2认同)

Hades32.. 98

给出的答案非常好,只是一个学术观点:

理论计算机科学意义上的正则表达式不是这样做的.对他们来说,它必须看起来像这样:

^([^h].*$)|(h([^e].*$|$))|(he([^h].*$|$))|(heh([^e].*$|$))|(hehe.+$) 

这只是完全匹配.为子匹配做这件事甚至会更加尴尬.

  • @JohnAllen:**我!!!**......好吧,不是实际的正则表达式,而是学术参考,这也与计算复杂性密切相关; PCRE从根本上不能保证与POSIX正则表达式相同的效率. (7认同)
  • 我同意.许多(如果不是大多数)正则表达式不是常规语言,并且无法被有限自动机识别. (5认同)
  • 对不起 - 这个答案不起作用,它会匹配hhehe甚至部分匹配hehe(下半场) (4认同)

Roy Tinker.. 57

如果您希望正则表达式测试整个字符串匹配时失败,则以下内容将起作用:

^(?!hede$).*

例如 - 如果你想允许除"foo"之外的所有值(即"foofoo","barfoo"和"foobar"将通过,但"foo"将失败),请使用: ^(?!foo$).*

当然,如果你正在检查确切的相等性,那么在这种情况下更好的通用解决方案是检查字符串是否相等,即

myStr !== 'foo'

如果您需要任何正则表达式功能(这里是不区分大小写和范围匹配),您甚至可以将否定置于测试之外:

!/^[a-f]oo$/i.test(myStr)

然而,在需要正面的正则表达式测试的情况下(可能通过API),此答案顶部的正则表达式解决方案可能会有所帮助.

  • @eagor:`^(?!\ s * hede \ s * $)。*` (2认同)

akim.. 53

FWIW,因为常规语言(也称为理性语言)在互补下被关闭,所以总是可以找到否定另一个表达式的正则表达式(也称为理性表达式).但实现这一点的工具并不多.

Vcsn支持此运算符(它表示{c}后缀).

标签信(:你先定义表达式的类型lal_char),从挑选az(与互补工作时定义的字母,当然是非常重要的),例如,与"价值"计算每个字仅仅是一个布尔:true这个词被接受了false,被拒绝了.

在Python中:

In [5]: import vcsn
        c = vcsn.context('lal_char(a-z), b')
        c
Out[5]: {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z} ? 

然后输入你的表达式:

In [6]: e = c.expression('(hede){c}'); e
Out[6]: (hede)^c

将此表达式转换为自动机:

In [7]: a = e.automaton(); a

相应的自动机

最后,将此自动机转换回简单表达式.

In [8]: print(a.expression())
        \e+h(\e+e(\e+d))+([^h]+h([^e]+e([^d]+d([^e]+e[^]))))[^]*

其中+通常被表示|,\e表示空字,并且[^]通常被写成.(任何字符).所以,稍微重写一下()|h(ed?)?|([^h]|h([^e]|e([^d]|d([^e]|e.)))).*.

你可以在这里看到这个例子,并在那里尝试在线Vcsn .

  • 真实,但丑陋,只适用于小字符集.您不希望使用Unicode字符串执行此操作:-) (6认同)
  • @PedroGimeno当你锚定时,你确保先把这个正则表达式放在parens中吗?否则,锚点和"|"之间的优先级将无法很好地发挥作用.`'^(()| H(编辑)|?([^ H] | H([^ E] | E(^ d] | d([^ E] |..E))))*) $'`. (3认同)

Josh Lee.. 51

这里有一个很好的解释为什么否定任意正则表达式并不容易.我不得不同意其他答案:如果这不是一个假设的问题,那么正则表达式不是正确的选择.

  • 有些工具,特别是mysqldumpslow,只提供这种方式来过滤数据,所以在这种情况下,找到一个正则表达式来做这个是除了重写工具之外的最佳解决方案(MySQL AB/Sun没有包含这方面的各种补丁)/Oracle. (10认同)

小智.. 43

使用负向前瞻,正则表达式可以匹配不包含特定模式的内容.Bart Kiers回答并解释了这一点.很棒的解释!

但是,根据Bart Kiers的回答,前瞻部分将在匹配任何单个字符时测试前方1到4个字符.我们可以避免这种情况,让前瞻部分检查整个文本,确保没有'hede',然后正常部分(.*)可以一次吃掉整个文本.

这是改进的正则表达式:

/^(?!.*?hede).*$/

注意负前瞻部分中的(*?)惰性量词是可选的,你可以使用(*)贪心量词,取决于你的数据:如果'hede'确实存在,并且在文本的开头一半,懒惰量词可以更快; 否则,贪婪量词会更快.但是,如果'hede'不存在,两者都会相等.

这是演示代码.

有关前瞻的更多信息,请查看精彩的文章:掌握Lookahead和Lookbehind.

另外,请查看RegexGen.js,这是一个JavaScript正则表达式生成器,可帮助构建复杂的正则表达式.使用RegexGen.js,您可以以更易读的方式构造正则表达式:

var _ = regexGen;

var regex = _(
    _.startOfLine(),             
    _.anything().notContains(       // match anything that not contains:
        _.anything().lazy(), 'hede' //   zero or more chars that followed by 'hede',
                                    //   i.e., anything contains 'hede'
    ), 
    _.endOfLine()
);

  • 所以简单地检查给定的字符串是否不包含str1和str2:`^(?!.*(str1 | str2)).*$` (3认同)

Falco.. 41

基准

我决定评估一些呈现的选项并比较它们的性能,以及使用一些新功能..NET Regex引擎的基准测试:http://regexhero.net/tester/

基准文字:

前7行不匹配,因为它们包含搜索的表达式,而较低的7行应该匹配!

Regex Hero is a real-time online Silverlight Regular Expression Tester.
XRegex Hero is a real-time online Silverlight Regular Expression Tester.
Regex HeroRegex HeroRegex HeroRegex HeroRegex Hero is a real-time online Silverlight Regular Expression Tester.
Regex Her Regex Her Regex Her Regex Her Regex Her Regex Her Regex Hero is a real-time online Silverlight Regular Expression Tester.
Regex Her is a real-time online Silverlight Regular Expression Tester.Regex Hero
egex Hero egex Hero egex Hero egex Hero egex Hero egex Hero Regex Hero is a real-time online Silverlight Regular Expression Tester.
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRegex Hero is a real-time online Silverlight Regular Expression Tester.

Regex Her
egex Hero
egex Hero is a real-time online Silverlight Regular Expression Tester.
Regex Her is a real-time online Silverlight Regular Expression Tester.
Regex Her Regex Her Regex Her Regex Her Regex Her Regex Her is a real-time online Silverlight Regular Expression Tester.
Nobody is a real-time online Silverlight Regular Expression Tester.
Regex Her o egex Hero Regex  Hero Reg ex Hero is a real-time online Silverlight Regular Expression Tester.

结果:

结果是每秒迭代次数为3次运行的中位数 - 更大的数字=更好

01: ^((?!Regex Hero).)*$                    3.914   // Accepted Answer
02: ^(?:(?!Regex Hero).)*$                  5.034   // With Non-Capturing group
03: ^(?>[^R]+|R(?!egex Hero))*$             6.137   // Lookahead only on the right first letter
04: ^(?>(?:.*?Regex Hero)?)^.*$             7.426   // Match the word and check if you're still at linestart
05: ^(?(?=.*?Regex Hero)(?#fail)|.*)$       7.371   // Logic Branch: Find Regex Hero? match nothing, else anything

P1: ^(?(?=.*?Regex Hero)(*FAIL)|(*ACCEPT))  ?????   // Logic Branch in Perl - Quick FAIL
P2: .*?Regex Hero(*COMMIT)(*FAIL)|(*ACCEPT) ?????   // Direct COMMIT & FAIL in Perl

由于.NET不支持动作动词(*FAIL等),我无法测试解决方案P1和P2.

摘要:

我试图测试大多数提议的解决方案,某些优化可能对某些单词有效.例如,如果搜索字符串的前两个字母不相同,则可以扩展答案03以 ^(?>[^R]+|R+(?!egex Hero))*$获得较小的性能增益.

但总体上最具可读性和性能最快的解决方案似乎是05使用条件语句或04使用积极量词.我认为Perl解决方案应该更快,更容易阅读.

  • 你应该时间`^(?!.*hede)`.///此外,分别对匹配语料库和非匹配语料库的表达式进行排序可能更好,因为它通常是大多数行匹配或大多数行不匹配的情况. (4认同)

小智.. 32

不是正则表达式,但我发现使用带管道的串行greps来消除噪音是合乎逻辑且有用的.

例如.在没有所有评论的情况下搜索apache配置文件 -

grep -v '\#' /opt/lampp/etc/httpd.conf      # this gives all the non-comment lines

grep -v '\#' /opt/lampp/etc/httpd.conf |  grep -i dir

串行grep的逻辑是(不是注释)和(匹配dir)

  • 这很危险.还错过了'good_stuff#comment_stuff`这样的行 (9认同)
  • 我想他正在要求`grep -v`的正则表达式版本 (2认同)

Casimir et H.. 29

有了这个,你就可以避免在每个位置测试前瞻:

/^(?:[^h]+|h++(?!ede))*+$/

相当于(for .net):

^(?>(?:[^h]+|h+(?!ede))*)$

老答案:

/^(?>[^h]+|h+(?!ede))*$/

  • 好点子; 我很惊讶之前没有人提到这种方法.但是,当应用于不匹配的文本时,该特定正则表达式容易出现[灾难性回溯](http://www.regular-expressions.info/catastrophic.html).这是我怎么做的:`/ ^ [^ h]*(?:h +(?!ede)[^ h]*)*$ /` (7认同)

ikegami.. 21

前面提到(?:(?!hede).)*的很好,因为它可以锚定.

^(?:(?!hede).)*$               # A line without hede

foo(?:(?!hede).)*bar           # foo followed by bar, without hede between them

但在这种情况下,以下就足够了:

^(?!.*hede)                    # A line without hede

这种简化已准备好添加"AND"子句:

^(?!.*hede)(?=.*foo)(?=.*bar)   # A line with foo and bar, but without hede
^(?!.*hede)(?=.*foo).*bar       # Same


ridgerunner.. 19

这是我如何做到的:

^[^h]*(h(?!ede)[^h]*)*$

比其他答案准确而有效.它实现了Friedl的"展开循环"效率技术,并且需要更少的回溯.


diyism.. 17

如果你想匹配一个字符来否定一个类似于否定字符类的单词:

例如,一个字符串:

<?
$str="aaa        bbb4      aaa     bbb7";
?>

不使用:

<?
preg_match('/aaa[^bbb]+?bbb7/s', $str, $matches);
?>

使用:

<?
preg_match('/aaa(?:(?!bbb).)+?bbb7/s', $str, $matches);
?>

注意"(?!bbb)."既不是lookbehind也不是lookahead,它是lookcurrent,例如:

"(?=abc)abcde", "(?!abc)abcde"

  • perl regexp中没有"lookcurrent".这确实是一个负面的前瞻(前缀`(?!`).正向前瞻的前缀是`(?=`而相应的lookbehind前缀将是`(?<!`和`(?<=`).前瞻意味着你在不消耗它们的情况下阅读下一个字符(因此是"未来").一个lookbehind意味着你检查已经被消费的字符. (3认同)

staafl.. 14

在我看来,最佳答案的可读性更高:

^(?!.*hede)

基本上,“仅当行中没有'hede'时,才在行的开头进行匹配”-因此,要求几乎直接转换为regex。

当然,可能有多种故障要求:

^(?!.*(hede|hodo|hada))

详细信息: ^锚确保正则表达式引擎不会在字符串的每个位置(将匹配每个字符串)重试匹配项。

开头的^锚点代表行的开头。grep工具一次匹配每一行,在使用多行字符串的情况下,可以使用“ m”标志:

/^(?!.*hede)/m # JavaScript syntax

要么

(?m)^(?!.*hede) # Inline flag


Kevin Fegan.. 13

OP未指定或Tag指示正在使用Regex的上下文(编程语言,编辑器,工具)的帖子.

对我来说,我有时需要在使用时编辑文件时这样做Textpad.

Textpad 支持一些正则表达式,但不支持前瞻或后瞻,所以它需要几个步骤.

如果我想保留所有包含字符串的行hede,我会这样做:

1.搜索/替换整个文件,以在包含任何文本的每行的开头添加唯一的"标记".

    Search string:^(.)  
    Replace string:<@#-unique-#@>\1  
    Replace-all  

2.删除包含该字符串的所有行hede(替换字符串为空):

    Search string:<@#-unique-#@>.*hede.*\n  
    Replace string:<nothing>  
    Replace-all  

3.此时,所有剩余的行都不包含字符串hede.从所有行中删除唯一的"Tag"(替换字符串为空):

    Search string:<@#-unique-#@>
    Replace string:<nothing>  
    Replace-all  

现在您有原始文本,其中所有行都包含hede删除的字符串.


如果我正在寻找Do Something Else只有包含字符串的行hede,我会这样做:

1.搜索/替换整个文件,以在包含任何文本的每行的开头添加唯一的"标记".

    Search string:^(.)  
    Replace string:<@#-unique-#@>\1  
    Replace-all  

2.对于包含该字符串的所有行hede,删除唯一的"Tag":

    Search string:<@#-unique-#@>(.*hede)
    Replace string:\1  
    Replace-all  

3.此时,所有以唯一"标记"开头的行都不包含字符串hede.我现在可以做我的其他东西了.

4.完成后,我从所有行中删除唯一的"Tag"(替换字符串为空):

    Search string:<@#-unique-#@>
    Replace string:<nothing>  
    Replace-all  


aelor.. 11

自从引入ruby-2.4.1以来,我们可以在Ruby的正则表达式中使用新的Absent Operator

来自官方文件

(?~abc) matches: "", "ab", "aab", "cccc", etc.
It doesn't match: "abc", "aabc", "ccccabc", etc.

因此,在您的情况下,为您^(?~hede)$完成工作

2.4.1 :016 > ["hoho", "hihi", "haha", "hede"].select{|s| /^(?~hede)$/.match(s)}
 => ["hoho", "hihi", "haha"]


Avinash Raj.. 9

通过PCRE动词 (*SKIP)(*F)

^hede$(*SKIP)(*F)|^.*$

这将完全跳过包含确切字符串的行hede并匹配所有剩余行.

DEMO

执行部件:

让我们通过将它分成两部分来考虑上面的正则表达式.

  1. |符号前面的部分.部分不应该匹配.

    ^hede$(*SKIP)(*F)
    
  2. |符号之后的部分.部分应该匹配.

    ^.*$
    

第1部分

正则表达式引擎将从第一部分开始执行.

^hede$(*SKIP)(*F)

说明:

  • ^ 断言我们刚开始.
  • hede 匹配字符串 hede
  • $ 断言我们在线端.

所以包含字符串的hede行将匹配.一旦正则表达式引擎看到以下内容(*SKIP)(*F)(注意:您可以写(*F)(*FAIL))动词,它会跳过并使匹配失败.|在PCRE动词旁边添加了一个名为alteration或逻辑OR运算符,它匹配所有行中每个字符之间的所有边界,除了该行包含精确的字符串hede.请在此处查看演示.也就是说,它尝试匹配剩余字符串中的字符.现在第二部分的正则表达式将被执行.

第2部分

^.*$

说明:

  • ^ 断言我们刚开始.即,它匹配除hede行中的那一行之外的所有行开始.请在此处查看演示.
  • .*在多行模式下,.将匹配除换行符或回车符之外的任何字符.并且*会重复前一个字符零次或多次.所以.*会匹配整条线.请在此处查看演示.

    嘿,为什么你添加.*而不是.+?

    因为.*匹配空行但.+不匹配空白.我们希望匹配所有行,除了hede输入中可能还有空行.所以你必须使用.*而不是.+..+将重复前一个字符一次或多次.请参阅此处.*匹配空白行.

  • $ 这里不需要行锚的结束.


Pedro Gimeno.. 9

由于没有其他人直接回答被问到的问题,我会这样做.

答案是,使用POSIX grep,不可能真正满足这个要求:

grep "<Regex for 'doesn't contain hede'>" input

原因是POSIX grep只需要使用Basic Regular Expressions,它根本不足以完成该任务(由于缺少交替和分组,它们无法解析常规语言).

但是,GNU grep实现了允许它的扩展.特别\|是GNU实现BRE的交替运算符,\(并且\)是分组运算符.如果你的正则表达式引擎支持交替,负括号表达式,分组和Kleene星,并且能够锚定到字符串的开头和结尾,这就是这种方法所需要的.

使用GNU [^ ... ],它将是这样的:

grep "^\([^h]\|h\(h\|eh\|edh\)*\([^eh]\|e[^dh]\|ed[^eh]\)\)*\(\|h\(h\|eh\|edh\)*\(\|e\|ed\)\)$" input

(与Grail和手工制作的一些进一步优化相结合).

您还可以使用实现扩展正则表达式的工具,例如(a|b|c| ... ),去掉反斜杠:

egrep "^([^h]|h(h|eh|edh)*([^eh]|e[^dh]|ed[^eh]))*(|h(h|eh|edh)*(|e|ed))$" input

这是一个测试它的脚本(注意它grep在当前目录中生成一个文件):

#!/bin/bash
REGEX="^\([^h]\|h\(h\|eh\|edh\)*\([^eh]\|e[^dh]\|ed[^eh]\)\)*\(\|h\(h\|eh\|edh\)*\(\|e\|ed\)\)$"

# First four lines as in OP's testcase.
cat > testinput.txt <<EOF
hoho
hihi
haha
hede

h
he
ah
head
ahead
ahed
aheda
ahede
hhede
hehede
hedhede
hehehehehehedehehe
hedecidedthat
EOF
diff -s -u <(grep -v hede testinput.txt) <(grep "$REGEX" testinput.txt)

在我的系统中打印:

Files /dev/fd/63 and /dev/fd/62 are identical

正如所料.

对于那些对细节感兴趣的人,采用的技术是将匹配单词的正则表达式转换为有限自动机,然后通过将每个接受状态更改为不接受而反之亦然,反之亦然,然后将生成的FA转换回一个正则表达式.

最后,正如每个人都注意到的,如果你的正则表达式引擎支持负向前瞻,那么这会简化任务.例如,使用GNU grep:

grep -P '^((?!hede).)*$' input

更新:我最近发现了Kendall Hopkins的优秀FormalTheory库,用PHP编写,提供类似于Grail的功能.使用它,以及我自己编写的简化器,我已经能够编写一个带有输入短语的负正则表达式的在线生成器(目前只支持字母数字和空格字符):http://www.formauri.es/personal/ pgimeno /杂项/不匹配正则表达式/

对于egrep它输出:

^([^h]|h(h|e(h|dh))*([^eh]|e([^dh]|d[^eh])))*(h(h|e(h|dh))*(ed?)?)?$

这相当于上述.


andrew pate.. 7

代码中的两个正则表达式可能更易于维护,一个用于执行第一个匹配,然后如果匹配则运行第二个正则表达式以检查您希望阻止的异常情况,例如^.*(hede).*在代码中具有适当的逻辑.

好的,我承认这不是对发布的问题的真正答案,它也可能比单个正则表达式使用稍多的处理.但对于那些来到这里寻找快速紧急修复异常情况的开发人员来说,这个解决方案不应该被忽视.


Kaz.. 5

TXR语言支持正则表达式的否定.

$ txr -c '@(repeat)
@{nothede /~hede/}
@(do (put-line nothede))
@(end)'  Input

一个更复杂的示例:匹配以_开头a和结尾的所有行z,但不包含子字符串hede:

$ txr -c '@(repeat)
@{nothede /a.*z&~.*hede.*/}
@(do (put-line nothede))
@(end)' -
az         <- echoed
az
abcz       <- echoed
abcz
abhederz   <- not echoed; contains hede
ahedez     <- not echoed; contains hede
ace        <- not echoed; does not end in z
ahedz      <- echoed
ahedz

正则表达式否定本身并不特别有用,但是当你也有交集时,事情变得有趣,因为你有一套完整的布尔集操作:你可以表达"匹配这个的集合,除了与之匹配的东西".


归档时间:

查看次数:

3155992 次

最近记录:

9 月,3 周 前