模式搜索与特殊字符

时间:2014-07-23 18:06:10

标签: java regex pattern-matching

您好我想搜索并获取索引所有特殊字符,如此

这样的复杂字符串
String textWithSpecialChars = "text here |*more*| text some other |@tags@|...";

我试图搜索所有模式|* |_ |= |@*| _| =| @|我尝试这种模式

public int getIndexOfPat(String s){
    Pattern startPat = Pattern.compile("\\|[\\*_@=]");
    Matcher matcher = pattern.matcher(s);
    return matcher.find() ? matcher.start() : -1;
}

String textWithSpecialChars = "text here |*more*| text some other |@tags@|...";
int i = getIndexOfPat(textWithSpecialChars);
textWithSpecialChars = textWithSpecialChars.substring(i+2);
//I get error here
i = getIndexOfPat(textWithSpecialChars);
// var i still is the first one value

但即使我用

删除原始字符串,它也只能得到第一个

2 个答案:

答案 0 :(得分:2)

您可以找到所有由特殊字符分隔的文本,而不是查找每个模式匹配的开头:

public List<String> getSpecialTextList(String line) {
    List<String> toRet = new ArrayList<String>();

    Pattern pattern = Pattern.compile("\\|([\\*_@=])((?:.(?!\\|))*)\\1\\|");
    Matcher matcher = pattern.matcher(line);
    while (matcher.find()) {
      toRet.add(matcher.group(2));
    }

    return toRet;
}

然后您可以这样使用它:

String textWithSpecialChars = "text here |*more*| text some other |@tags@|...";
List<String> specialTextList = getSpecialTextList(textWithSpecialChars);
System.out.println(specialTextList); // prints [more, tags]

请注意,这不适用于|*hello|*there*|*|

等嵌套代码

答案 1 :(得分:2)

您的问题是,每次调用getIndexOfPat时,您正在重新创建Matcher实例(并且模式,但重新编译模式在这里不是问题,它只是无效的代码)。因此,每次拨打find时,它都会尝试从头开始查找匹配项。

您可以选择如何解决此问题。

  1. 让所有创建的比赛的方法返回列表
  2. 传递Matcher的方法实例,这样你就可以在Matcher上调用find,它会记住最后一次匹配的位置,然后搜索它。
  3. 我会选择选项1,因为选项2只是包装find方法并返回其结果,感觉有点太简单的代码而不是单独的方法,如

    int getNextIndex(Matcher m){
        return matcher.find() ? matcher.start() : -1;
    }
    

    选项1看起来像

    static Pattern pattern = Pattern.compile("[|]([*_@=])[^|]+\\1[|]");
    
    public static List<Integer> getMatchedIntexes(String s) {
        List<Integer> result = new ArrayList<>();
        Matcher m = pattern.matcher(s);
        while (m.find()){
            result.add(m.start()+1);//index of character after `|`
            result.add(m.end()-1);  //index of character before `|`
        }
    
        return result;
    }
    

    你可以像

    一样使用它
    String textWithSpecialChars = "text here |*more*| text some other |@tags@|...";
    
    for (int index : getMatchedIntexes(textWithSpecialChars))
        System.out.println(index);
    

    会打印

    11
    17
    36
    42
    

    [|]([*_@=])[^|]+\\1[|]

    的说明
    • [|]与代表\\|字面值的|相同
    • ([*_@=])创建的第1组只能包含*_@=
    • [^|]+会匹配一系列不是|的字符系列(我假设您在|内没有任何嵌套|*...*|。如果你确实将它改为.*?,效率可能会降低
    • \\1表示来自第1组的匹配,因此您只能找到|*..*|个部分,而不是|*.._|
    • 前面提到的
    • [|]代表|字面意思。