代码之家  ›  专栏  ›  技术社区  ›  John

regex匹配除给定列表之外的所有单词

  •  18
  • John  · 技术社区  · 17 年前

    我正在尝试编写一个替换正则表达式,用引号将所有单词括起来,除了单词“和”、“或”和“否”。

    对于表达式的匹配部分,我尝试了以下操作:

    (?i)(?<word>[a-z0-9]+)(?<!and|not|or)
    

    (?i)(?<word>[a-z0-9]+)(?!and|not|or)
    

    但两者都不起作用。替换表达式很简单,目前包含所有单词。

    "${word}"
    

    所以

    这个和这个不是那个

    变成

    “这个”和“这个”不是“那个”

    5 回复  |  直到 14 年前
        1
  •  14
  •   Tomalak    17 年前

    这有点脏,但它起作用:

    (?<!\b(?:and| or|not))\b(?!(?:and|or|not)\b)
    

    在纯英语中,这匹配任何单词边界,而不是在其前面,也不是在其后面加上“and”、“or”或“not”。它只匹配整个单词,例如,单词“sand”后面的位置不会是匹配项,因为它前面有“and”。

    “或”前面的空间在零宽度“向后看”断言中是必要的,以便使其成为固定长度的向后看。如果这已经解决了你的问题,试试看。

    编辑:应用于字符串“除了单词和、或与否”。作为全局替换,用单引号替换,返回:

    'except' 'the' 'words' AND, OR and NOT.
    
        2
  •  5
  •   Jan Goyvaerts    17 年前

    厕所,

    你问题中的正则表达式几乎是正确的。唯一的问题是您将lookahead放在regex的末尾,而不是开始。此外,还需要添加单词边界以强制regex匹配整个单词。否则,它将匹配“nd”in“and”、“r”in“or”等,因为“nd”和“r”不在您的否定前瞻中。

    ?(b)?![AZ-9+])-B

        3
  •  3
  •   Marc Gravell    17 年前

    称我为疯子,但我不喜欢和regex战斗;我把我的模式限制在我能理解的简单的事情上,并且经常欺骗其他人-例如通过 MatchEvaluator :

        string[] whitelist = new string[] { "and", "not", "or" };
        string input = "foo and bar or blop";
        string result = Regex.Replace(input, @"([a-z0-9]+)",
            delegate(Match match) {
                string word = match.Groups[1].Value;
                return Array.IndexOf(whitelist, word) >= 0
                    ? word : ("\"" + word + "\"");
            });
    

    (为更简洁的布局而编辑)

        4
  •  2
  •   Markus Jarderot    17 年前

    根据Tomalaks的回答:

    (?<!and|or|not)\b(?!and|or|not)
    

    此regex有两个问题:

    1. (?<! ) 仅适用于固定长度的后视镜

    2. 前一个regex只查看周围单词的结束/开始,而不是整个单词。

    (?<!\band)(?<!\bor)(?<!\bnot)\b(?!(?:and|or|not)\b)

    这个regex解决了上述两个问题。首先,将后面的视图分成三个单独的视图。第二种方法是添加单词边界( \b )在环顾四周。

        5
  •  0
  •   bluish dmajkic    14 年前
    (?!\bnot\b|\band\b|\bor\b|\b\"[^"]+\"\b)((?<=\s|\-|\(|^)[^\"\s\()]+(?=\s|\*|\)|$))
    

    我使用这个regex查找所有不在双引号内的单词或单词“not”和“or”。