5

我正在尝试获取输入字符串中与给定模式匹配的所有子字符串。

例如,

给定字符串:aaxxbbaxb
模式:a[az]{0,3}b
(我真正想表达的是:所有以a开头和以b结尾的模式,但它们之间最多可以有2个字母)

我想要的确切结果(及其索引):

aaxxb:索引 0~4
axxb:索引 1~4
axxbb:索引 1~5
axb:索引 6~8

Pattern.compile()但是当我使用and通过 Pattern 和 Matcher 类运行它时Matcher.find(),它只给了我:

aaxxb : 索引 0~4
axb : 索引 6~8

这是我使用的一段代码。

Pattern pattern = Pattern.compile("a[a-z]{0,3}b", Pattern.CASE_INSENSITIVE);
Matcher match = pattern.matcher("aaxxbbaxb");
while (match.find()) {
    System.out.println(match.group());
}

如何检索与模式匹配的每一段字符串

当然,它不必使用 Pattern 和 Matcher 类,只要它是高效的 :)

4

3 回答 3

3

(请参阅:与 java regex 匹配的所有重叠子字符串

这是我想出的完整解决方案。它可以处理原始正则表达式中的零宽度模式、边界等。它查看文本字符串的所有子字符串,并通过在开头和结尾使用适当数量的通配符填充模式来检查正则表达式是否仅在特定位置匹配。它似乎适用于我尝试过的案例——尽管我没有进行广泛的测试。它肯定比它可能的效率低。

  public static void allMatches(String text, String regex)
  {
    for (int i = 0; i < text.length(); ++i) {
      for (int j = i + 1; j <= text.length(); ++j) {
        String positionSpecificPattern = "((?<=^.{"+i+"})("+regex+")(?=.{"+(text.length() - j)+"}$))";
        Matcher m = Pattern.compile(positionSpecificPattern).matcher(text);

        if (m.find()) 
        {   
          System.out.println("Match found: \"" + (m.group()) + "\" at position [" + i + ", " + j + ")");
        }   
      }   
    }   
  }
于 2012-07-05T18:42:16.690 回答
1

您实际上是在输入字符串中搜索字符串 ab、a_b 和 a__b,其中 _ 表示您不关心其值的非空白字符。

这是三个搜索目标。我能想到的最有效的方法是使用像Knuth-Morris-Pratt算法这样的搜索算法,并进行一些修改。实际上,您的伪代码将类似于:

for i in 0 to sourcestring.length
    check sourcestring[i] - is it a? if so, check sourcestring[i+x] 
       // where x is the index of the search string - 1
    if matches then save i to output list
    else i = i + searchstring.length

显然,如果您有位置匹配,则必须检查子字符串的内部字符以确保它们是按字母顺序排列的。

运行算法 3 次,每个搜索词运行一次。毫无疑问,它比尝试使用模式匹配进行搜索要快得多。

编辑 - 抱歉,没有正确阅读问题。如果您必须使用正则表达式,那么上述内容将不适合您。

于 2011-09-06T10:54:33.407 回答
0

你可以做的一件事是:

  • 创建所有可能的 4 个字符或更长的子字符串(如果您的字符串很大,祝您好运)
  • 为这些子字符串中的每一个创建一个新的匹配器
  • 做一个 match() 而不是 find()
  • 根据子字符串的相对偏移量和匹配器信息计算绝对偏移量
于 2011-09-06T10:38:56.557 回答