0

ユーザー定義トークンのセットで正規表現を実行する必要があります。

たとえば、次のような文字列があります: TOK3 TOK1 TOK2 TOK2 TOK4 TOK3// example string

そして、次のような正規表現を使用します: (TOK1|TOK2)+// regexp

一連のトークンをキャプチャしたいと思います:TOK1 TOK2 TOK2私の例の文字列で。

現在、正規表現は通常、一連の文字で機能するため、トークンが文字ではなく文字列であるという意味で、私の問題は少し異なります。私のトークンは、2 つ以上の文字で構成されている可能性があります。さらに、私のソフトウェアは、例の正規表現が位置 (1, 4) の文字列と一致することを検出できるはずです。

とりあえず、各トークンを ASCII アルファベットの char にマッピングし、スペースを削除した後に正規表現を実行することで問題を解決しました。

しかし、私はこの解決策に完全に満足しているわけではなく、より良い解決策があるかどうか疑問に思っていました. ありがとう!

編集

正規表現内のスペースは、トークンを区切るためにのみ必要です。トークン間にスペースが必須であるという意味ではありません。

4

2 に答える 2

3

あなたの例に従って、これはうまくいくはずです:

(?:(?:TOK1|TOK2|...)(?: |$))+

Matcher#start メソッドは、マッチの開始位置を示します。

それでも、とても簡単に思えるので、あなたの質問には何かが欠けているような気がします...

于 2013-04-05T12:06:28.310 に答える
1

すべてのスペースの位置を保存し、これを使用して文字列の位置をトークンの位置に変換するのはどうですか?

ストレートな正規表現ほどエレガントではありませんが、それはアイデアです。

TreeMap<Integer, Integer> spaces = new TreeMap<Integer, Integer>();
String regex = "(?<=^| )((TOK1|TOK2)( |$))+";
String str = "TOK3 TOK1 TOK2 TOK2 TOK4 TOK3";
int c = 0;
spaces.put(0, 0);
for (int i = 0; i < str.length(); i++)
{
   if (str.charAt(i) == ' ')
     spaces.put(i, ++c);
}
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
while (m.find()) {
   System.out.println(m.group());
   System.out.println("start = " + spaces.floorEntry(m.start()).getValue());
   System.out.println("finish = " + spaces.floorEntry(m.end()).getValue());
}

別のオプションはString.split次のとおりです。

String str = "TOK3 TOK1 TOK2 TOK2 TOK4 TOK3";
String[] arr = str.split(" "); // maybe consider using \\s or \\s+ instead
int start = -1;
String match = "";
for (int i = 0; i < arr.length; i++)
{
   if (arr[i].matches("(TOK1|TOK2)"))
   {
      if (start == -1)
         start = i;
      match += ((match.length() != 0) ? " " : "") + arr[i];
   }
   else if (start != -1)
   {
      System.out.println(match);
      System.out.println("start = " + start);
      System.out.println("finish = " + i);
      match = "";
      start = -1;
   }
}
于 2013-04-05T12:47:32.043 に答える