Java正则表达式:重复的分组?

huangapple go评论85阅读模式
英文:

Java Regex: repetitive groups?

问题

怎样在Java正则表达式中定义重复的分组?

假设有多个由逗号分隔的两位数 [0-9]{2},

这样的形式:12,34,98,11

这是否有可能?还是只有通过逗号进行分割的机会?

编辑:我想要同时验证和提取。

英文:

How can I define repetitive groups in Java Regex?

Lets say a 2digit number [0-9]{2} multiple times separates by ,

12,34,98,11

Is that possible or a split by , the only chance?

Edit: I like to validate AND extract.

答案1

得分: 1

在Java中,您还可以使用Scanner API来实现此操作:

final Pattern pat = Pattern.compile("\\d{2}");
Scanner scan = new Scanner("12,34,98,11");
scan.useDelimiter(",");
while(scan.hasNext(pat)) {
    System.out.println("Token: " + scan.next());
}
scan.close();
英文:

In Java you may also use Scanner APIs for this:

final Pattern pat = Pattern.compile("\\d{2}");
Scanner scan = new Scanner("12,34,98,11");
scan.useDelimiter(",");
while(scan.hasNext(pat)) {
	System.out.println(	"Token: " + scan.next() );
}
scan.close();

答案2

得分: 1

这在Java正则表达式中是支持的。请参阅Pattern文档。以下是一个示例:

"11,12,13".matches("\\d{2}(,\\d{2})*"); // true

然后,您可以使用String.split()ScannerStringTokenizer来分割字符串。示例如下:

String[] split = "11,12,13".split(",");
StringTokenizer stringTokenizer = new StringTokenizer("11,12,13", ",");
Scanner scanner = new Scanner("11,12,13").useDelimiter(",");
while (scanner.hasNext()) {
    // scanner.next()
}
英文:

That's supported in Java Regex. See Pattern documentation. Here's an example:

"11,12,13".matches("\\d{2}(,\\d{2})*"); // true

You can then split the string with String.split(), a Scanner or a StringTokenizer. Examples:

String[] split = "11,12,13".split(",");
StringTokenizer stringTokenizer = new StringTokenizer("11,12,13", ",");
Scanner scanner = new Scanner("11,12,13").useDelimiter(",");
while (scanner.hasNext()) {
	// scanner.next()
}

答案3

得分: 0

The simplest way is to use a two-step solution: 1) first, validate the string, then 2) split the string with the delimiter of your choice:

String[] chunks = null;
if (s.matches("\\d{2}(?:,\\d{2})*")) {
    chunks = s.split(Pattern.quote(","));
    System.out.println(Arrays.toString(chunks)); // => [12, 34, 98, 11]
}

Here, s.matches("\\d{2}(?:,\\d{2})*") matches the whole string that starts with two digits and then contains 0 or more occurrences of , and two digits to the end, and then s.split(Pattern.quote(",")) splits the string with a comma. Note you do not need ^ and $ anchors with a pattern inside matches() since the method requires a full string match.

If you have to do that with a single regex, you may use multiple matches anchored to the start of string and end of each successful preceding match, only if the string check at the start of the string is a success:

(?:\G(?!^),|^(?=\d{2}(?:,\d{2})*$))(\d{2})

Details

  • (?:\G(?!^),|^(?=\d{2}(?:,\d{2})*$)) - end of the preceding successful match and then a , (see \G(?!^),) or (|) start of string (^) that is followed with two digits and then 0 or more sequences of a , and two digits to the end of the string (see \d{2}(?:,\d{2})*$)
  • (\d{2}) - Group 1: two digits

Java demo:

String s = "12,34,98,11";
Pattern p = Pattern.compile("(?:\\G(?!^),|^(?=\\d{2}(?:,\\d{2})*$))(\\d{2})");
Matcher m = p.matcher(s);
List<String> results = new ArrayList<>();
while(m.find()) {
    results.add(m.group(1));
}
System.out.println(results);
// => [12, 34, 98, 11]
英文:

The simplest way is to use a two-step solution: 1) first, validate the string, then 2) split the string with the delimiter of your choice:

String[] chunks = null;
if (s.matches(&quot;\\d{2}(?:,\\d{2})*&quot;)) {
    chunks = s.split(Pattern.quote(&quot;,&quot;));
    System.out.println(Arrays.toString(chunks)); // =&gt; [12, 34, 98, 11]
}

Here, s.matches(&quot;\\d{2}(?:,\\d{2})*&quot;) matches the whole string that starts with two digits and then contains 0 or more occurrences of , and two digits to the end, and then s.split(Pattern.quote(&quot;,&quot;)) splits the string with a comma. Note you do not need ^ and $ anchors with a pattern inside matches() since the method requires a full string match.

If you have to do that with a single regex, you may use multiple matches anchored to the start of string and end of each successful preceding match, only if the string check at the start of the string is a success:

(?:\G(?!^),|^(?=\d{2}(?:,\d{2})*$))(\d{2})

See the regex demo.

Details

  • (?:\G(?!^),|^(?=\d{2}(?:,\d{2})*$)) - end of the preceding successful match and then a , (see \G(?!^),) or (|) start of string (^) that is followed with two digits and then 0 or more sequences of a , and two digits to the end of the string (see \d{2}(?:,\d{2})*$)
  • (\d{2}) - Group 1: two digits

Java demo:

String s = &quot;12,34,98,11&quot;;
Pattern p = Pattern.compile(&quot;(?:\\G(?!^),|^(?=\\d{2}(?:,\\d{2})*$))(\\d{2})&quot;);
Matcher m = p.matcher(s);
List&lt;String&gt; results = new ArrayList&lt;&gt;();
while(m.find()) {
	results.add(m.group(1));
}
System.out.println(results); 
// =&gt; [12, 34, 98, 11]

huangapple
  • 本文由 发表于 2020年4月8日 02:35:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/61087035.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定