Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
与java正则表达式匹配的所有重叠子字符串_Java_Regex_Matcher - Fatal编程技术网

与java正则表达式匹配的所有重叠子字符串

与java正则表达式匹配的所有重叠子字符串,java,regex,matcher,Java,Regex,Matcher,是否有API方法返回与正则表达式匹配的所有(可能重叠)子字符串 例如,我有一个文本字符串:string t=04/31412-555-1235,我有一个模式:模式p=new模式(\\d\\d+) 我得到的匹配是:04、31、412、555、1235 如何获得重叠匹配 我希望代码返回:04、31、41、412、12、55、555、55、12、123、1235、23、235、35 理论上这应该是可能的——有一个明显的O(n^2)算法,它根据模式枚举并检查所有子字符串 编辑 使用Matcher中的区域

是否有API方法返回与正则表达式匹配的所有(可能重叠)子字符串

例如,我有一个文本字符串:
string t=04/31412-555-1235,我有一个模式:
模式p=new模式(\\d\\d+)

我得到的匹配是:04、31、412、555、1235

如何获得重叠匹配

我希望代码返回:04、31、41、412、12、55、555、55、12、123、1235、23、235、35

理论上这应该是可能的——有一个明显的
O(n^2)
算法,它根据模式枚举并检查所有子字符串

编辑

使用
Matcher
中的
区域(int start,int end)
方法比枚举所有子字符串更安全。根据单独提取的子字符串检查模式可能会更改匹配结果(例如,如果模式的开始/结束处存在非捕获组或字边界检查)

编辑2

实际上,还不清楚
region()
是否达到了零宽度匹配的预期效果。规范含糊不清,实验结果令人失望

例如:

String line = "xx90xx";
String pat = "\\b90\\b";
System.out.println(Pattern.compile(pat).matcher(line).find()); // prints false
for (int i = 0; i < line.length(); ++i) {
  for (int j = i + 1; j <= line.length(); ++j) {
    Matcher m = Pattern.compile(pat).matcher(line).region(i, j);
    if (m.find() && m.group().size == (j - i)) {
      System.out.println(m.group() + " (" + i + ", " + j + ")"); // prints 90 (2, 4)
    }
  }
}
编辑4

这里有一个更好的方法:

编辑5

该库支持查找与java正则表达式匹配的所有重叠子字符串(尽管它似乎在一段时间内没有更新)。具体而言,该文件规定:

使用非中断搜索,您可以查找所有可能发生的故障 模式,包括相交或嵌套的模式。这是 通过使用Matcher的方法procedure()而不是find()实现


你能得到的最接近的东西是这样的

"(?=((\\d*)\\d))(?=(\\d)\\d*)"
结果将是捕获组1、2和3

就我的想象而言,我只能将捕获零长度断言视为重新捕获字符串相同位置的可行方法。捕获零长度断言之外的文本将一次性使用文本(look behind在Java中只能捕获固定长度的文本,因此可以认为它是不可访问的)

这个解决方案并不完美:除了重复(相同位置的文本!)和空字符串匹配之外,它不会捕获所有可能的子字符串

捕获所有可能的子字符串的一种方法是构造以下值为n的正则表达式,从1开始:

"(?=(\\d{" + n + "}))"
并将字符串与此匹配,以增加n的值,直到没有匹配为止

当然,与使用“\d+”匹配所有数字并提取所有子字符串的方法相比,此方法效率低下。

只有在指定允许的数字长度范围时,才可以使用O(n)

让我们从2-4位数字(数字00-9999)开始:
(?=(\\d{2}))(?=(\\1\\d)?)(?=(\\2\\d)?)

这是一个通过正向前瞻的零长度断言,将此类前瞻捕获到组中。结果是在regex输入中可以找到的所有2-4位字符串的数组,以及重复字符串和空字符串(对于非匹配捕获)

我不是Java开发人员,但我相信Perl脚本也可以作为示例阅读

#!/usr/bin/perl                                       # perl script
use List::MoreUtils qw/ uniq /;                       # uniq subroutine library
$_ = '04/31 412-555-1235';                            # input
my @n = uniq (/(?=(\d{2}))(?=(\1\d)?)(?=(\2\d)?)/g);  # regex (single slash in Perl)
print "$_\n" for grep(/\S/, @n);                      # print non-empty lines
诀窍是使用反向引用。如果要捕获2-5位字符串,则需要在正则表达式中使用一个更积极的前瞻:
(?=(\\d{2}))(?=(\\1\\d)?(?=(\\2\\d)?)(?=(\\3\\d)?)


我相信这是你能采取的最接近的方法。如果这对您有效,请发表评论,希望一些Java开发人员会使用上述脚本的Java代码编辑我的答案。

我遇到了类似的情况,我尝试了上述答案,但在我的情况下,设置匹配器的开始和结束索引花费了太多时间 但我认为我找到了一个更好的解决方案,我在这里发布给其他人。 下面是我的代码剪

if (textToParse != null) {
Matcher matcher = PLACEHOLDER_PATTERN.matcher(textToParse);
    while(matcher.hitEnd()!=true){
        Boolean result = matcher.find();
        int count = matcher.groupCount();
        System.out.println("Result " +result+" count "+count);
        if(result==true && count==1){
            mergeFieldName = matcher.group(1);
            mergeFieldNames.add(mergeFieldName);
           }
       }
  }
我已经使用matcher.hitEnd()方法来检查是否已到达文本的末尾

希望这有帮助。
谢谢

只要做一个post-regex循环,通过所有3个或更多的字符,结果可能是进行挖掘的好地方@Ωmega尽了我最大的努力,但对无用的反馈持开放态度。干杯。我想正则表达式不会重复扫描。干草堆中的角色只能使用一次。我能想到的最接近的方法是一场不激烈的比赛。但这只会返回12,35,不会得到1235。重复:正则表达式在Java中是相同的(除了反斜杠需要转义)。至于
uniq
,它可以用Java中的
Set
TreeSet
HashSet
)进行模拟。@nhahtdh-谢谢。请随意添加更新到我的答案编辑后。
if (textToParse != null) {
Matcher matcher = PLACEHOLDER_PATTERN.matcher(textToParse);
    while(matcher.hitEnd()!=true){
        Boolean result = matcher.find();
        int count = matcher.groupCount();
        System.out.println("Result " +result+" count "+count);
        if(result==true && count==1){
            mergeFieldName = matcher.group(1);
            mergeFieldNames.add(mergeFieldName);
           }
       }
  }