替换字符串中的子字符串,除非字符串在引号内

时间:2011-07-21 12:00:11

标签: java regex

正则表达方言:爪哇语 问题:给定一个字符串,替换其中出现的所有子字符串,除非这些出现在引号内。

例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 个答案:

答案 0 :(得分:4)

这是一种方式:

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

因为它“看到”前面的偶数个单引号( i ii )。你必须强制它查看它右边的整个字符串(一直到$)!