首页 文章

当文本用双引号括起时,转义文本中的特殊字符

提问于
浏览
4

我正在编写一个正则表达式来逃避一些特殊字符,包括输入中的双引号 .

输入可以用双引号括起来,那些不应该被转义 .

输入结果:

"te(st", te(st, te"st

预期产出:

"te\(st", te\(st, te\"st

使用的代码:

String regex = "^\".*\"$";
    String value = "\"strin'g\"";
    Pattern SPECIAL_REGEX_CHARS = Pattern.compile("[()'"\\[\\]*]");

    if (Pattern.matches(regex, value)){
        String val = value.substring(1, value.length() -1);
        String replaceAll = SPECIAL_REGEX_CHARS.matcher(val).replaceAll("\\\\$0");
        replaceAll = "\""+replaceAll+"\"";
        System.out.println(replaceAll);
    }else {
        String replaceAll = SPECIAL_REGEX_CHARS.matcher(value).replaceAll("\\\\$0");
        System.out.println(replaceAll);
    }

1 - 检查文本是否用双引号括起来 . 如果是,则转义用双引号括起来的文本中的特殊字符 .

2 - 别的 . 转义文本中的特殊字符 .

任何可以组合#1和#2的正则表达式?

此致,Anil

2 回答

  • 0

    只有一个转义正则表达式的简单解决方案

    您可以使用 if (s.startsWith("\"") && s.endsWith("\"")) 检查字符串是否同时包含前导和尾随 " ,如果是,则可以使用 replaceAll("^\"|\"$", "") 修剪前导和尾随 " ,然后使用转义正则表达式转义,然后再添加 " . 否则,只需要逃避你集合中的角色 .

    String SPECIAL_REGEX_CHARS = "[()'\"\\[\\]*]";
    String s = "\"te(st\""; // => "te\(st"
    String result;
    if (s.startsWith("\"") && s.endsWith("\"")) {
        result = "\"" + s.replaceAll("^\"|\"$", "").replaceAll(SPECIAL_REGEX_CHARS, "\\\\$0") + "\"";
    }
    else {
        result = s.replaceAll(SPECIAL_REGEX_CHARS, "\\\\$0");
    }
    System.out.println(result.toString());
    

    看另一个IDEONE demo

    使用appendReplacement“回调”的替代解决方案

    以下是使用替换的一个正则表达式的方法:

    String SPECIAL_REGEX_CHARS = "[()'\"\\[\\]*]";
    //String s = "\"te(st\""; // => "te\(st"
    //String s = "te(st"; // => te\(st
    String s = "te\"st"; // => te\"st
    StringBuffer result = new StringBuffer();
    Matcher m = Pattern.compile("(?s)\"(.*)\"|(.*)").matcher(s);
    if (m.matches()) {
        if (m.group(1) == null) { // we have no quotes around
            m.appendReplacement(result, m.group(2).replaceAll(SPECIAL_REGEX_CHARS, "\\\\\\\\$0"));
        }
        else {
            m.appendReplacement(result, "\"" + m.group(1).replaceAll(SPECIAL_REGEX_CHARS, "\\\\\\\\$0") + "\"");
        }
    }
    m.appendTail(result);
    System.out.println(result.toString());
    

    IDEONE demo

    要点:

    • Matcher#addReplacement()Matcher#appendTail()允许操纵组 .

    • 使用带有2个备用分支的 (?s)\"(.*)\"|(.*) 正则表达式: ".*" 匹配以 " 开头并以 " 结尾的字符串(注意 (?s) 是DOTALL内联修饰符,允许匹配字符串与换行符序列)或 .* 替代匹配所有其他字符串 .

    • 如果第一个选项匹配,我们只需替换第一个捕获组中选定的特殊字符,然后在两端添加 " .

    • 如果匹配第二个备选方案,只需在整个第2组中添加转义符号即可 .

    • 要替换为文字反斜杠,您需要在替换模式中使用 \\\\\\\\ .

  • 0

    您可以使用negative lookbehind and lookahead

    System.out.println(value.replaceAll("([()'\\[\\]*]|(?<!^)\"(?!$))", "\\\\$0"));
    

    这基本上是说:转义字符类 [()'\[\]*] 中的任何内容,或任何 " 之前没有字符串开头或后面跟着字符串结尾 .

    唯一的问题是,无论在另一端是否有相应的报价,都会忽略前导和尾随报价 . 如果这是一个问题,您可以链接这些替换以逃避不匹配的前导或尾随引用:

    .replaceAll("^\".*[^\"]$", "\\\\$0")
    .replaceAll("(^[^\"].*)(\"$)", "$1\\\\$2")
    

相关问题