替换字符串中的子字符串,但不包括在引号内的字符串

4
正则表达式方言:Java
问题:给定一个字符串,在不影响引号内的情况下,替换其中所有子字符串的出现。
例1:
string: "test substr 'test substr' substr"
substring: "substr"
replacement: "YYYY"
output: "test YYYY 'test substr' YYYY"

例子2:

string: "test sstr 'test sstr' sstr"
substring: "substr"
replacement: "YYYY"
output: "test sstr 'test sstr' sstr"

示例3:

string: "test 'test substr'"
substring: "substr"
replacement: "YYYY"
output: "test 'test substr'"

这是我迄今为止的最佳尝试:
Regex: ((?:[^']*'[^']+')*?[^']*?)substring
Replace: $1replacement

问题在于它需要在引号内最后一个字符串之后加上一个引号外的子字符串,否则它就无法工作,因此Example3将失败(输出:“test 'test YYYY'”)。

非常感谢您的帮助。

1个回答

5
这里有一个方法:
public class Main {
    public static void main(String [] args) {

        String[] tests = {
                "test substr 'test substr' substr",
                "test sstr 'test sstr' sstr",
                "test 'test substr'"
        };

        String regex = "substr(?=([^']*'[^']*')*[^']*$)";

        for(String t : tests) {
            System.out.println(t.replaceAll(regex, "YYYY"));
        }
    }
}

输出:

test YYYY 'test substr' YYYY
test sstr 'test sstr' sstr
test 'test substr'

请注意,如果'可以通过\进行转义,则此方法不起作用。

简单解释一下:

([^']*'[^']*')*将匹配0个或偶数个单引号,并在其间匹配非引号字符,[^']*$将匹配任何非引号字符以及字符串结尾。

因此,完整的正则表达式substr(?=([^']*'[^']*')*[^']*$)将匹配任何具有0个或偶数个单引号的"substr"当一直查找到字符串结尾时!

这里的关键是一直查找到字符串结尾。如果你不这样做,下面的"substr"也会被替换:

aaa 'substr' bbb 'ccc ddd' eee
           ^     ^       ^
           |     |       |
           i     ii     iii

因为它在其前面“看到”了偶数个单引号(iii),所以需要强制它查看其右侧的整个字符串(一直到$)!


非常感谢你,Bart!不知怎么的,我一直在复制粘贴,从来没有想过往前看。 - Marius Burz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接