Regex 不是在正则表达式中

Regex 不是在正则表达式中,regex,Regex,如何构建一个正则表达式来匹配所有具有ABC、DBE、ABE、FBG等的序列,但不匹配XBZ 我的示例序列ABC、DBE等仅具有代表性。我不是在寻找那些特定的模式。A、 B、C、D、E等可以采取任何形式。例如,X、B和Z可以是单词 具体来说,我希望找到所有包含B但前面没有X或后面没有Z的实例 我使用grep-v选项提出了一个解决方案,该选项可反转匹配: cat文件| grep-ne.*B.*| grep-ve“XBZ” 但是我宁愿使用一个正则表达式。您可以使用否定的前瞻断言来实现这一点 (?!^X

如何构建一个正则表达式来匹配所有具有ABC、DBE、ABE、FBG等的序列,但不匹配XBZ

我的示例序列ABC、DBE等仅具有代表性。我不是在寻找那些特定的模式。A、 B、C、D、E等可以采取任何形式。例如,X、B和Z可以是单词

具体来说,我希望找到所有包含B但前面没有X或后面没有Z的实例

我使用
grep-v
选项提出了一个解决方案,该选项可反转匹配:

cat文件| grep-ne.*B.*| grep-ve“XBZ”


但是我宁愿使用一个正则表达式。

您可以使用否定的前瞻断言来实现这一点

(?!^XBZ$)

虽然正则表达式在否定条件下是闭合的,但在标准正则表达式中没有否定运算符。这纯粹是语法问题,没有什么可以阻止正则表达式引擎编写器在语法中添加非标准的否定运算符。。。因此,必须将其改写为一组备选方案:

^([^X]..X[^B].[XB[^Z])$

我不知道更好的方法


另外,在
[…]
内部有一个否定运算符
^
,但它只匹配单个字符。上面已经用过了。

我写了一个函数,根据我评论中的假设编写正则表达式。以下是假设:

  • 这是三个字符串
  • 字符一取自字母表
  • 第二个角色总是一样的。在OP的帖子里,这是B
  • 第三个字符是第一个字符+1
  • 字符1和字符3不能等于字符2

    static void writeRegex(char skip)
    {
    string mydocpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
    StringBuilder sb = new StringBuilder();
    sb.Append("^(");
    char one = 'A';
    char two = 'B';
    bool first = true;
    for (; one < 'Z' && two <= 'Z' ; )
    {
        if (!first)
        {
            sb.Append("|");   
        }
        first = false;
    
        if (one == skip)
        {
            one++;
        }
        if (two == skip || one == two)
        {
            two++;
        }
    
        sb.Append(one.ToString() + skip.ToString() + two.ToString());
    
        one++;
        two++;
    }
    sb.Append(")$");
    
    using (StreamWriter outfile = new StreamWriter(mydocpath + @"\Regex.txt"))
    {
        outfile.Write(sb.ToString());
    }
    
    static void writeRegex(字符跳过)
    {
    字符串mydocpath=Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
    StringBuilder sb=新的StringBuilder();
    某人附加(“^”);
    char one='A';
    char two='B';
    bool first=true;
    
    对于(;one<'Z'&&two,W3C用于指定的符号,或者具有用于排除的
    -
    运算符,并且可以非常方便地使用它。例如,请参见(不区分大小写)排除“XML”一词的示例:

    基于DFA的正则表达式引擎可以利用正则表达式在差分下是闭合的这一事实,轻松支持这种排除,但您发现它很少实现

    有一个解析器/词法生成器,使用W3C符号。它将在某个时候开放源代码,但我需要更多的时间来提供一些缺失的部分,尤其是文档

    使用该符号,您的示例可以如下所示:

    Letter ::= [A-Z]
    Three-Letter-Code ::= (Letter Letter Letter) - 'XBZ'
    

    我认为人们对这个问题想得太多了。如果我正确理解了这个问题——你希望正则表达式匹配一组特定的序列,而不是其他特定的序列——答案就是你不必告诉正则表达式什么不匹配。它只匹配符合你指定的模式的内容,而不匹配其他内容。
    ABC|DBE | ABE | FBG
    匹配ABC或DBE或ABE或FBG,并且不匹配任何其他序列,包括XBZ。您不必特别指示它不匹配XBZ。

    需要一段时间才能到达,但此模式:

    (.*((?!X).B|B(?!Z).))|(^B)|(B$)
    
    查找(非X的对象)B或B(非Z的对象)。TDD代码如下所示:

    [Test]
    public void TestPattern()
    {
        const string pattern = "(.*((?!X).B|B(?!Z).))|(^B)|(B$)";
    
        Assert.IsFalse(Regex.IsMatch("Hello", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello ABC", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello DBE", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello ABE", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello FBG", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello ABC World", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello DBE World", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello ABE World", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello FBG World", pattern));
        Assert.IsTrue(Regex.IsMatch("ABC World", pattern));
        Assert.IsTrue(Regex.IsMatch("DBE World", pattern));
        Assert.IsTrue(Regex.IsMatch("ABE World", pattern));
        Assert.IsTrue(Regex.IsMatch("FBG World", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello DBE World XBZ", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello ABE World XBZ", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello FBG World XBZ", pattern));
        Assert.IsFalse(Regex.IsMatch("Hello XBZ", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello XB", pattern));
        Assert.IsTrue(Regex.IsMatch("Hello BZ", pattern));
        Assert.IsTrue(Regex.IsMatch("XB Hello", pattern));
        Assert.IsTrue(Regex.IsMatch("BZ Hello", pattern));
        Assert.IsTrue(Regex.IsMatch("B", pattern));
    }
    

    下面是一种perl方法来完成这项工作:

    my $re = qr/(?<!X)B(?!Z)/;
    while(<DATA>) {
        chomp;
        say /$re/ ? "OK : $_" : "KO : $_";
    }
    __DATA__
    ABC
    DBE
    ABE
    FBG
    XBZ
    
    说明:

    OK : ABC
    OK : DBE
    OK : ABE
    OK : FBG
    KO : XBZ
    
    (?-imsx:(?<!X)B(?!Z))
    
    matches as follows:
    
    NODE                     EXPLANATION
    ----------------------------------------------------------------------
    (?-imsx:                 group, but do not capture (case-sensitive)
                             (with ^ and $ matching normally) (with . not
                             matching \n) (matching whitespace and #
                             normally):
    ----------------------------------------------------------------------
      (?<!                     look behind to see if there is not:
    ----------------------------------------------------------------------
        X                        'X'
    ----------------------------------------------------------------------
      )                        end of look-behind
    ----------------------------------------------------------------------
      B                        'B'
    ----------------------------------------------------------------------
      (?!                      look ahead to see if there is not:
    ----------------------------------------------------------------------
        Z                        'Z'
    ----------------------------------------------------------------------
      )                        end of look-ahead
    ----------------------------------------------------------------------
    )                        end of grouping
    ----------------------------------------------------------------------
    

    (?-imsx:(?
    XBZ
    为什么是奇数?请解释。您的意思是“除XBZ外的所有三个大写字母序列”还是“除XBZ外的所有三个大写字母序列,B是第二个?”还有,为什么ABE被接受?你是想输入EBF吗?你描述的模式似乎是:选择字母表中的一个字母:
    H
    称之为
    letterOne
    。取字母表中的下一个字母:
    I
    ,称之为
    letterTwo
    。制作一个字符串:
    letterOne+“B”+letterTwo
    。什么是“等等”意思是说?
    grep
    可以处理文件,你不需要
    cat | grep
    grep“[^X]B[^Z]”文件就是你要找的。这可以匹配无限长的行,我假设OP总共需要3个字符。ABC/*7984.,作为匹配项。@Michael Davis:似乎不起作用。
    cat file | grep-P”(?!^XBZ$)
    输出整个文件。@Rob Lyndon:您的表达式不包括XBZ,但匹配其他任何内容,例如AAAAAAA。这一点很好。我认为Michael试图解决更困难的负匹配问题,我也做了同样的事情。我添加了一个答案,应该可以解决整个问题。问题是我不知道另一个答案可能的模式包括B在中间。A,C,D,E等可以是任何东西。好,我明白你的意思。“具体地说,我正在寻找所有包含B但不在X之前或后面没有Z的实例”。我将在几分钟内更新答案。?我希望这个问题的答案是肯定的——与B匹配就足够了。这似乎确实有效!感谢Rob。对于使用
    grep
    ,必须使用Perl regex引擎,这是
    -P
    开关。更多信息如下:
    (?-imsx:(?<!X)B(?!Z))
    
    matches as follows:
    
    NODE                     EXPLANATION
    ----------------------------------------------------------------------
    (?-imsx:                 group, but do not capture (case-sensitive)
                             (with ^ and $ matching normally) (with . not
                             matching \n) (matching whitespace and #
                             normally):
    ----------------------------------------------------------------------
      (?<!                     look behind to see if there is not:
    ----------------------------------------------------------------------
        X                        'X'
    ----------------------------------------------------------------------
      )                        end of look-behind
    ----------------------------------------------------------------------
      B                        'B'
    ----------------------------------------------------------------------
      (?!                      look ahead to see if there is not:
    ----------------------------------------------------------------------
        Z                        'Z'
    ----------------------------------------------------------------------
      )                        end of look-ahead
    ----------------------------------------------------------------------
    )                        end of grouping
    ----------------------------------------------------------------------