正则表达式匹配模式和组正确的元素

时间:2015-12-09 04:25:06

标签: java regex pattern-matching

我有以下类型的字符串

//ABCD E 1234 L1
//ABCD E 1234,2345 L2
//ABCD E 4567
//ABCD E 2435,4679

为了匹配上面的字符串,我写了下面的模式。

Pattern.compile("//\\s*ABCD\\s+E\\s+(((\\d*,\\s*\\d*)*)|(\\d*+(((,\\s*\\d*,\\s*\\d*)*)))+)\\s*(.*?)",
        Pattern.CASE_INSENSITIVE);

以上所有字符串都符合上述模式。 但是当我试图获得ABCD E之后的数字,即组(1)并获得标签即组(8)时,我得到了错误的结果。

// ABCD E 1234 L1和// ABCD E 4567给出了错误的结果。  group(1)对于两个字符串都是空的,而group(8)是1234 L1和4567。

我怀疑(。*?)是我猜的罪魁祸首,但我不确定还有什么用。

如果有人知道匹配上述字符串的好模式,请告诉我。

P.S:ABCD E之后的数字是1234,2345,456等.L1和L2被称为标签。基本上在ABCD E之后它可能只是没有任何标签的数字(标签是no和charctaetrs的混合)或者数字和标签,

我想要单独的数字和标签

4 个答案:

答案 0 :(得分:1)

您可以尝试:

(\s*ABCD\s+E\s+)(?<num>[\d,]+)\s*(?<label>[A-Z]\d)?
  • (\s*ABCD\s+E\s+) - 捕捉必要的部分,
  • (?<num>[\d,]+) - 捕获数字和逗号
  • (?<label>[A-Z]\d)? - 如果有,请抓取大写字母后跟数字,

DEMO

最多可以获取3个捕获的组,例如将num组与,分开以获得多个数字。或者您可以尝试:

(?<pre>ABCD\s*E\s*)|(?<=\G),?(?<num>\d+)|(?<=\G)\s*(?<label>[A-Z]\d)
  • (?<pre>ABCD\s*E\s*) - 捕获组合ABCD E
  • | - 或
  • (?<=\G),?(?<num>\d+) - 捕获四位数字,前面是另一位数字 捕获的片段,可选地用逗号
  • | - 或
  • (?<=\G)\s*(?<label>[A-Z]\d) - 捕获大写字母后跟 digit,preceeedec由另一个捕获的片段,optionaly with spaces

DEMO

获取不同比赛中的数字和标签。但是,如果要从中提取此数据的文本包含更多类似的组合,则可以提供更多输出,但这取决于其余的背景文本。

答案 1 :(得分:0)

^\s*(\/\/ABCD)\s+(E)\s+(\d+([,.]\d+)?)\s+([A-Z0-9]*)?

#0  //ABCD E 1234 L1
#1  //ABCD
#2  E
#3  1234
#4  null
#5  L1

答案 2 :(得分:0)

我认为最好的方法是使用正则表达式提取包含数字的字符串的逗号分隔部分,然后用逗号分割此匹配项以获取所需的单个数字。

<强>输出:

String input = "ABCD E 456,7689,687 M1X";

Pattern pattern = Pattern.compile("[^0-9]*\\s([0-9,]*)\\s([^0-9].*)");
Matcher queryMatcher = pattern.matcher(input);

String csvMatch = "";
String otherMatch = "";
if (queryMatcher.find()) {
    csvMatch   = queryMatcher.group(1);
    otherMatch = queryMatcher.group(2);
}
String[] matches = csvMatch.split(",");

for (String match : matches) {
    System.out.println("Found a number: " + match);
}
System.out.println("Found other: " + otherMatch);

您可以通过以下链接测试正则表达式:

Found a number: 456
Found a number: 7689
Found a number: 687
Found other: M1X

Regex101

答案 3 :(得分:0)

如果你想要的只是数字部分和标签部分,你可以简化正则表达式:

ABCD E (\d+(?:,\d+)*)(?: (\w+))?

<强>勒亘

ABCD E      # matches literal string 'ABCD E ', note the empty spaces
(           # open capturing group 1
 \d+        # matches 1 or more digits
 (?:,\d+)*  # non capturing group: matches comma followed by 1 or more digits. Can be zero o more time repeated
)           # close capturing group 1
(?:         # a non capturing group
            # a literal empty space ' '
 (\w+)      # capturing group 2 composed by 1 or more of [a-zA-Z0-9_]
)?          # close the non capturing group and make it optional

添加一定的灵活性(用带有标签的组替换空格[ \t])以上内容变为:

ABCD[ \t]+E[ \t]+(\d+(?:,\d+)*)(?:[ \t]+(\w+))?

正则表达式演示

Link

代码演示

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

String ln    = System.lineSeparator();
String input = "ABCD E 1234 L1"      + ln
             + "ABCD E 1234,2345 L2" + ln
             + "ABCD E 4567"         + ln
             + "ABCD E 2435,4679"    + ln
             + "ABCD E 2435,4679,657 L6";

final Pattern labelPattern = Pattern.compile("ABCD[ \\t]+E[ \\t]+(\\d+(?:,\\d+)*)(?:[ \\t]+(\\w+))?");
Matcher m = labelPattern.matcher(input);

int line = 1;
while(m.find()) {
  System.out.print("Line " + line++ + ": ");

  if ( ! m.group(2) )
    System.out.println("'" + m.group(1) + "'"); // print number section
  else
    System.out.println("'" + m.group(1) + "', '" + m.group(2)+ "'"); // print numbers and label section
}

<强>输出

Line 1: '1234', 'L1'
Line 2: '1234,2345', 'L2'
Line 3: '4567'
Line 4: '2435,4679'
Line 5: '2435,4679,657', 'L6'