Java Regex:查找带转义的单引号文本

Posted

技术标签:

【中文标题】Java Regex:查找带转义的单引号文本【英文标题】:Java Regex: find single quoted text with escapes 【发布时间】:2019-12-30 20:03:47 【问题描述】:

此方法应返回所有出现的单引号字符串。但是,转义单引号 (\’) 应被视为常规单引号字符(就像 Java 中的转义双引号一样)。示例:“This ’isn\’t’ easy’”该方法应返回单个字符串 “isn’t”。 我的代码:

public static List<String> findSingleQuotedTextWithEscapes(String input) 
        Pattern pattern = Pattern.compile ("(?:\\w|'[^']*')+");
        Matcher matcher = pattern.matcher (input);
        ArrayList ans = new ArrayList();
        while (matcher.find ())
            ans.add (matcher.group ().replace ("'",""));
        
        return ans;
    

输入:"more'test'" 预期:[test] 实际:[more,test] 我似乎在捕捉 ' 字符时遇到了问题,我正在标记所有内容,请帮忙。 添加测试人员:

void fillSingleQuotedTestInputs(List<String> inputs, List<List<String>> expect) 
        inputs.add("'test'"); expect.add(Arrays.asList("test"));
        inputs.add("more'test'"); expect.add(Arrays.asList("test"));
        inputs.add("'test'more"); expect.add(Arrays.asList("test"));
        inputs.add("\\'no'yes'"); expect.add(Arrays.asList("yes"));
        inputs.add("a 'one' and 'two' and 'three'..."); expect.add(Arrays.asList("one", "two", "three"));
        inputs.add("nothing at all"); expect.add(Arrays.<String>asList());
        inputs.add("''"); expect.add(Arrays.asList(""));
        inputs.add("''test"); expect.add(Arrays.asList(""));
        inputs.add("test''"); expect.add(Arrays.asList(""));
        inputs.add("te''st"); expect.add(Arrays.asList(""));
        inputs.add("'This is not wrong' and 'this isn\\'t either'"); expect.add(Arrays.asList("This is not wrong", "this isn't either"));
        inputs.add("'tw\\'o repl\\'acements' in 't\\'wo stri\\'ngs'."); expect.add(Arrays.asList("tw'o repl'acements", "t'wo stri'ngs"));
        inputs.add("'\\''"); expect.add(Arrays.asList("'"));
        inputs.add("'''"); expect.add(Arrays.asList(""));
        inputs.add("'test1'\n'test2'"); expect.add(Arrays.asList("test1", "test2"));
        inputs.add("''''"); expect.add(Arrays.asList("", "")); // This one is hard. Hint: \G
    

    @Test
    public void testFindSingleQuotedTextWithEscapes() 
        ArrayList<String> inputs = new ArrayList<String>();
        ArrayList<List<String>> expect = new ArrayList<List<String>>();

        fillSingleQuotedTestInputs(inputs, expect);

        for (int i = 0; i < inputs.size(); ++i) 
            List<String> output = RegexpPractice.findSingleQuotedTextWithEscapes(inputs.get(i));
            assertEquals(String.format("Test %d failed: Search <<%s>>", i, inputs.get(i)), expect.get(i), output);
        
    

【问题讨论】:

\w+\\’\w+ 有什么问题吗? 不会捕捉到任何单词中间有 ' 的东西 我明白了,所以你需要一些环顾四周。 (?&lt;=’)\w+(?:\\’\w+)*(?=’)regex101.com/r/dNQoCF/1 如果没有环视,我将如何做到这一点? 为什么? Java 支持环视,所以使用环视。 【参考方案1】:

看起来(?&lt;!\\)'(.*?)(?&lt;!\\)' 将满足您的所有需求。它使用否定的lookbehind 来断言,当匹配' 时,它后面没有\。这会通过代码中显示的所有测试用例。

Demo

如果您想在没有环视的情况下执行此操作,可以使用(?:[^'\n\r]*?'()'|[^\\]'(.*?[^\\])')。请注意,这比显示的第一个正则表达式执行得更慢。

Demo

【讨论】:

谢谢,虽然它确实需要对add 进行一些修改所以我将添加更改为:ans.add (matcher.group ().replaceAll ("'","").replace ("\\","'")); 如果问题在双引号中,那将如何改变答案? 没有环视怎么办? @Yuki1112 更新了正则表达式的答案,没有环视。请注意,它的执行速度比原来的要慢;它尚未经过严格测试,但与您的所有测试用例匹配。 谢谢,但是由于某种原因,它会将字符串的第一个字符添加到答案中,这是为什么呢?【参考方案2】:

注意反斜杠吃下一个字符或非撇号:

String s = "1.'2\'3\\'xx'x'";
//            [^^^^^^]  [^]

List<String> findQuotedText(Strings) 
    Pattern quotedPattern = Pattern.compile("'((\\\\.|[^\\\\']+)*)'");
    //                                        |    |    |        |
    //                                apostrophe   |    |       apostrophe
    //                                 backslash+any or non-apostrophes
    Matcher m = quotedPattern.matcher(s);
    List<String> results = new ArrayList<>();
    while (m.find()) 
        results.add(m.group(1));
    
    return results;

结果:

2'3\

【讨论】:

它在短语的开头起作用,但直到单词的结尾才继续,还请注意这是一个列表。示例:输入: fdsaf'te\'st'fdsafdsa 。预期:te'st 实际:te\ 已更正; \. 的替代方案必须包含非反斜杠。

以上是关于Java Regex:查找带转义的单引号文本的主要内容,如果未能解决你的问题,请参考以下文章

print()函数与转义字符

SQL中的单引号转义符

Oracle中的单引号怎么转义

python中的单引号,双引号和三双引号的区别

Java Regex 删除开始/结束单引号但保留在引号内

如何阻止 Swift 在我的 [String] 中注入转义的单引号?