【问题标题】:Regular expression to match unescaped special characters only正则表达式仅匹配未转义的特殊字符
【发布时间】:2011-08-21 16:32:17
【问题描述】:

我正在尝试提出一个正则表达式,它只能匹配字符串中前面没有特殊转义序列的字符。

例如,在字符串 Is ? stranded//? 中,我希望能够用另一个字符串替换尚未转义的 ?,所以我可以得到这样的结果:**Is Dave stranded?**

但是对于我的一生,我一直无法想出办法。我只提出了吃掉所有可替换字符的正则表达式。

如何构造一个只匹配前面没有转义序列的字符的正则表达式?

【问题讨论】:

    标签: java regex


    【解决方案1】:

    使用消极的后视,这是他们的设计目的!

    (?

    分解:

    (
        ?<!    #The negative look behind.  It will check that the following slashes do not exist.
        //     #The slashes you are trying to avoid.
    )
    [\?]       #Your special charactor list.
    

    只有在 // 找不到时,才会继续进行其余的搜索。

    我认为在 Java 中它需要再次转义为字符串,例如:

    Pattern p = Pattern.compile("(?<!//)[\\?]");
    

    【讨论】:

    • 如果有两个斜杠怎么办:\\? 然后第一个斜杠转义第二个,第二个不转义?
    【解决方案2】:

    试试这个 Java 代码:

    str="Is ? stranded//?";
    Pattern p = Pattern.compile("(?<!//)([?])");
    m = p.matcher(str);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
        m.appendReplacement(sb, m.group(1).replace("?", "Dave"));
    }
    m.appendTail(sb);
    String s = sb.toString().replace("//", "");
    System.out.println("Output: " + s);
    

    输出

    Output: Is Dave stranded?
    

    【讨论】:

    • 非常感谢 - 我发现这在进行参数化替换时特别有用,其中标记用作其他字符串的占位符
    【解决方案3】:

    我正在考虑这个问题,并有第二个更简单的解决方案,避免使用正则表达式。其他答案可能更好,但我想我还是可以发布它。

    String input = "Is ? stranded//?"; 
    String output = input
        .replace("//?", "a717efbc-84a9-46bf-b1be-8a9fb714fce8")
        .replace("?", "Dave")
        .replace("a717efbc-84a9-46bf-b1be-8a9fb714fce8", "?");
    

    只保护“//?”通过用独特的东西(如指南)替换它。那么你知道任何剩余的问号都是公平的游戏。

    【讨论】:

    • 如果您想要更多特殊字符,我想您可以使用正则表达式编写类似的版本。
    【解决方案4】:

    使用分组。这是一个例子:

    import java.util.regex.*;
    
    class Test {
        public static void main(String[] args) {
            Pattern p = Pattern.compile("([^/][^/])(\\?)");
            String s = "Is ? stranded//?";
            Matcher m = p.matcher(s);
            if (m.matches)
                s = m.replaceAll("$1XXX").replace("//", "");
            System.out.println(s + " -> " + s);
        }
    }
    

    输出:

    $ java Test
    Is ? stranded//? -> Is XXX stranded?
    

    在这个例子中,我是:

    • 首先替换任何未转义的 ?与“XXX”,
    • 然后,删除“//”转义序列。

    编辑使用if (m.matches) 确保您正确处理不匹配的字符串。

    这只是一个简单粗暴的例子。显然,您需要充实它,以使其更加健壮。但它传达了总体思路。

    【讨论】:

    • 如果输入字符串是? is stranded!会发生什么
    • 或者 indead 甚至只是一个斜线:Hello David/?
    • 是的,这是一个极端情况。我没有考虑这些就破解了这个。查看我的编辑。
    • 我打算将此作为一个快速示例,说明如何构建与所需子字符串匹配的正则表达式,而不是作为所有输入字符串的通用解决方案。我编辑了示例以表明真正的解决方案应该考虑这些边缘情况。
    【解决方案5】:

    匹配一组字符,而不是转义序列,然后是正则表达式特殊字符。您可以使用倒置字符类 ([^/]) 作为第一位。字符串前面未转义的正则表达式字符的特殊情况。

    【讨论】:

      【解决方案6】:
      String aString = "Is ? stranded//?";
      
      String regex = "(?<!//)[^a-z^A-Z^\\s^/]";
      System.out.println(aString.replaceAll(regex, "Dave"));
      

      正则表达式[^a-z^A-Z^\\s^/]的部分匹配非字母数字、空格或非正斜杠字符。

      (?&lt;!//) 部分进行了负面的向后看 - 请参阅 docco here 了解更多信息

      这给出了输出Is Dave stranded//?

      【讨论】:

        【解决方案7】:

        尝试匹配:

        (^|(^.)|(.[^/])|([^/].))[special characters list]
        

        【讨论】:

          【解决方案8】:

          我用过这个:

          ((?:^|[^\\])(?:\\\\)*[ESCAPABLE CHARACTERS HERE])
          

          演示:https://regex101.com/r/zH1zO3/4

          【讨论】:

            猜你喜欢
            • 2021-11-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-12-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-12-28
            相关资源
            最近更新 更多