正则表达式包括和排除转义序列

时间:2014-02-03 19:17:49

标签: java regex

我正在尝试找到一个带有以下数据的正则表达式模式:

static String testData = "0001,48;0451,0605\\,230001;0461,0606\\;230006;0431,0605230002";

并打印出以下组:

Group 1: 0001,48;
Group 2: 0451,0605\\,230001;
Group 3: 0461,0606\\;230006;
Group 4: 0431,0605230002;

我目前在解析'0605 \,230001'中出现的转义序列时效率不高。

static String testPattern = "([\\d]{4}" + "[,]{1}"+ "(?:[[a-zA-Z0-9][\\;][\\,][\\(][\\)][\\s]]*)"+ "[;]{1})" ;

如上所述,上述模式仅在打印方面有效:

Group 1: 0001,48;
Group 2: 0431,0605230001;

其余代码:

Pattern pattern=Pattern.compile(testPattern);
Matcher matcher = pattern.matcher(testData);

System.out.println("Test Matches: "+testData.matches(testPattern));

while(matcher.find())
{
    for (int i = 1; i <= matcher.groupCount(); i++) 
    {
        System.out.println("Group " + i + ": " + matcher.group(i));
    }
}

有没有办法让我们可以在模式中使用转义序列,并且在我们需要时也不会逃避它们?

4 个答案:

答案 0 :(得分:1)

如建议的那样。您可以使用String#split()方法使用正则表达式进行拆分。

请在此处查看此示例:

String testData = "0001,48;0451,0605\\,230001;0431,0605230002;";
String[] array = testData.split("(?<=[^\\]);");
for(int i = 0; i < array.length; i++)
{
    System.out.println(array[i]);
}

打印

"0001,48"
"0451,0605\\,230001"
"0431,0605230002"

然后,如果您将testData作为""0001,48;0451,0605\\;230001;0431,0605230002;"(请注意转义的;),则会打印

"0001,48"
"0451,0605\\;230001"
"0431,0605230002"

如果您最后需要分号,可以手动添加分号或使用此正则表达式,它将保留分号并仅在非转义分号上分割

"(?<=(?<=[^\\]);)"

答案 1 :(得分:1)

当您想要将输入拆分为;分隔的部分时,此模式应该有效:

"\\G([^;\\\\]|\\\\.)+;"

上面的正则表达式应该与Matcher.find()一起使用。请注意,您需要记录每次匹配后是否已到达输入结束,以便检查是否已消耗所有输入。

这应该适用于大量转义的输入(注意这是文本,而不是Java字符串文字):

456\\\;734;82734\\\\;574\;347;

(作为Java字符串文字:"456\\\\\\;734;82734\\\\\\\\;574\\;347;"

将分为:

456\\\;734;
82734\\\\;
574\;347;

如果;前面有偶数\,则表示\自行转义,因此;不会被转义。

答案 2 :(得分:0)

尝试代码

for(String str : testData.split("(?<=(?<!\\\\);)"))
{
    System.out.println(str);
}

使用String的.split()方法将字符串拆分为单独的部分,然后打印出每个部分。

如果您需要按照问题的方式实现正则表达式,请将此字符串用于正则表达式:

"+*?(?<=(?<!\\\\);)"

此处的解释和演示:http://regex101.com/r/vW0oT9

答案 3 :(得分:0)

通过了my answer的副本到另一个问题。

虽然实现自己的split()函数可能看起来像是一个开销,但我的解决方案可以正确处理包含反斜杠转义的分号和反斜杠的字符串,如

String input = "0001,48;0451,0605\\,230001\\\\;0461,0606\\;230006;0431,0605230002";

使用示例:

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Print {
    public static void main(final String[] args) {
        String input = "0001,48;0451,0605\\,230001\\\\;0461,0606\\;230006;0431,0605230002";
        final String[] strings = splitValues(input);
        System.out.print("\""+input+"\" => ");
        printQuoted(strings);
    }

    public static String[] splitValues(final String input) {
        final ArrayList<String> result = new ArrayList<String>();
        // (?:\\\\)* matches any number of \-pairs
        // (?<!\\) ensures that the \-pairs aren't preceded by a single \
        final Pattern pattern = Pattern.compile("(?<!\\\\)(?:\\\\\\\\)*;");
        final Matcher matcher = pattern.matcher(input);
        int previous = 0;
        while (matcher.find()) {
            result.add(input.substring(previous, matcher.end()));
            previous = matcher.end();
        }
        result.add(input.substring(previous, input.length()));
        return result.toArray(new String[result.size()]);
    }

    public static void printQuoted(final String[] strings) {
        if (strings.length > 0) {
            System.out.print("[\"");
            System.out.print(strings[0]);
            for(int i = 1; i < strings.length; i++) {
                System.out.print("\", \"");
                System.out.print(strings[i]);
            }
            System.out.println("\"]");
        } else {
            System.out.println("[]");
        }
    }
}

将打印

  

“0001,48; 0451,0605 \,230001 \\; 0461,0606 \; 230006; 0431,0605230002”=&gt; [“0001,48;”,“0451,0605 \,230001 \\;”,“0461,0606 \; 230006;”,“0431,0605230002”]

如果你不需要能够逃脱前面的反斜杠;比你应该没有内置的,例如this answer