正则表达式从字符串中提取n值

时间:2012-07-06 19:01:15

标签: regex

正则表达式是否可以提取字符串中嵌入的值,由先前在同一字符串中定义的变量模板标识?或者在Java中更好地处理它?<​​/ p>

例如:“2012法拉利[F12] - 鸵鸟皮内饰[F12#OL] - 糖果红金属[F12#3]”变量模板是方括号遇到的第一个字符串,例如: [F12],并且在该模板的后续实例中找到所需的变量,例如, 'OL'和'3'。

1 个答案:

答案 0 :(得分:0)

由于您提到Java,我假设您正在使用Java实现Pattern

Java模式支持所谓的后向引用,可用于匹配先前捕获组匹配的相同值。

遗憾的是,您无法从单个捕获组中提取多个值,因此如果您想使用单个模式执行此操作,则必须对要匹配的模板数进行硬编码。

对于一个变量,它可能如下所示:

\[(.*?)\].*?\[\1#(.*?)\]
  ^^^^^          ^^^^^ variable
 template     ^^ back reference to whatever template matched

您可以通过将它们包装在可选的非捕获组中来添加更多可选匹配项,如下所示:

\[(.*?)\].*?\[\1#(.*?)\](?:.*?\[\1#(.*?)\])?(?:.*?\[\1#(.*?)\])?
                        ^ optional group    ^ another one

这最多可以匹配三个变量:

    String s = "2012 Ferrari [F12] - Ostrich Leather interior [F12#OL] - Candy Red Metallic [F12#3]";
    String pattern = "\\[(.*?)\\].*?\\[\\1#(.*?)\\](?:.*?\\[\\1#(.*?)\\])?(?:.*?\\[\\1#(.*?)\\])?";
    Matcher matcher = Pattern.compile(pattern).matcher(s);
    if (matcher.find()) {
        for (int i = 1; i <= matcher.groupCount(); i++) {
            System.out.println(matcher.group(i));
        }
    }

    // prints F12, OL, 3, null

但是,如果你需要匹配任意数量的变量,你将不得不求助于在第一遍中提取模板,然后将其嵌入第二种模式中:

    // compile once and store in a static variable
    Pattern templatePattern = Pattern.compile("\\[(.*?)\\]");

    String s = "2012 Ferrari [F12] - Ostrich Leather interior [F12#OL] - Candy Red Metallic [F12#3]";

    Matcher templateMatcher = templatePattern.matcher(s);

    if (!templateMatcher.find()) {
        return;
    }

    String template = templateMatcher.group(1);
    Pattern variablePattern = Pattern.compile("\\[" + Pattern.quote(template) + "#(.*?)\\]");

    Matcher variableMatcher = variablePattern.matcher(s);
    while (variableMatcher.find()) {
        System.out.println(variableMatcher.group(1));
    }