正则表达式(警告:家庭作业)

时间:2014-02-03 18:35:05

标签: regex

我正在研究的部分家庭作业问题如下:

“构建一个正则表达式,捕获除文件以外的所有非空字母序列,用于或来自。为了符号方便,您可以假设存在一个not运算符,它将一组字母作为参数并匹配任何其他字母。 “

我想出的答案:

not(f[ile|or|rom])

也许我是偏执狂,但这似乎太容易了?我很感激任何评论,我知道这不可能是正确的。

4 个答案:

答案 0 :(得分:5)

[ile|or|rom]将与ile|or或{{1}匹配} 一次,因为m[中的字符是字符组。 ]符合[as]{3}aaasssasa等。

sas将与(ile|or|rom)ileor匹配。

也许你正在寻找

rom

答案 1 :(得分:2)

这个没有使用特殊(负面)的look-a-head语法。它的分支是为了排除无效状态。我只为文件创建它,因为它有点长。

^(f(i(l($|e.+$|[^e].*)|$|[^l].*$)|$|[^i].*)|[^f].*$)

这是regexp的(确定性)自动机(使用Regexper制作):

这使用了look-a-head:

^(?!f(ile|or|rom)$)[a-z]+$

答案 2 :(得分:1)

很难回答这样一个假设的正则表达式的问题。 2件事:

  1. 方括号内的字符定义character class。如果你想匹配“f”后跟“ile”或“or”或“rom”,请使用普通组

    f(ile|or|rom)
    
  2. 假设not(f(ile|or|rom))匹配任何字符,而不是任何字符的一部分,那么您需要quantifier来匹配重复的字符。

    not(f(ile|or|rom))+
    

    +一次或多次之前重复该项目

  3. <强>加成:

    使用negative lookahead assertion的真实世界解决方案将是

    \b((?!f(ile|or|rom)\b)\w)+\b
    

    here on Regexr

答案 3 :(得分:1)

向后执行以达到f(il,o,ro)

 #  (?s)(?:.(?<!file)(?<!for)(?<!from))+

修改
使用lookbehind永远是病态的 所以为了节省面子,下面是我知道的两种方式,以一种相当简单的方式。

首先是使用拆分,这是直截了当的。

 (?<=fil)(?=e)|(?<=fo)(?=r)|(?<=fro)(?=m)  

第二种方式相当简单。查找直到file|for|from开始 然后匹配任何剩余的fil|fo|fro 这将匹配每个角色,一个外观不会做的事情。

使用分割和直线正则表达式的示例都在测试用例中。

正则表达式解释

 #  (?s)(?:(?!file|for|from).())*(?:(?:fil|fo|fro)())?(?=\1|\2)

 (?s)                         # Dot-All
 (?:                          # Optional group, do many times
      (?! file | for | from )     # Lookahead, not 'file', 'for', 'from'
      .                           # Match this character
      ( )                         # Set a Group 1 flag (empty, but defined)
 )*
 (?:                          # Optional group, do once
      (?: fil | fo | fro )        # 'fil'(e), 'fo'(r), 'fro'(m)
      ( )                         # Set a Group 2 flag (empty, but defined)
 )?
 (?= \1 | \2 )                # See if we matched at least 1 character
                              # (this could be done with a conditional,
                              #  but not all engines have it)

Perl测试用例。

 $/ = undef;
 $str = <DATA>;

 # Using Split()

 my @ary = split(/(?<=fil)(?=e)|(?<=fo)(?=r)|(?<=fro)(?=m)/, $str);

 for (my $i = 0; $i < @ary; $i++)
 {
    print $ary[$i],"\n";
 }
 print "----------\n";

 # Using just Regex

 while ($str =~ /(?s)(?:(?!file|for|from).())*(?:(?:fil|fo|fro)())?(?=\1|\2)/g ) 
 {
    print $&, "\n";
 }
  __DATA__
 this file is a frozen filled football from Steve, for trackingfromforfile

输出&gt;&gt;

 this fil
 e is a frozen filled football fro
 m Steve, fo
 r trackingfro
 mfo
 rfil
 e
 ----------
 this fil
 e is a frozen filled football fro
 m Steve, fo
 r trackingfro
 mfo
 rfil
 e