37

この質問は長い間私を悩ませてきましたが、基本的には、2 つの文字列の間のすべての文字列を取得する最も効率的な方法を探しています。

私が何ヶ月もの間行ってきた方法は、一時的なインデックス、文字列、部分文字列の束を使用することであり、それは本当に面倒です. (Java に などのネイティブ メソッドがないのはなぜString substring(String start, String end)ですか?

文字列があるとします:

abcabc [pattern1]foo[pattern2] abcdefg [pattern1]bar[pattern2] morestuff

foo最終的な目標は、とを出力することbarです。(そして後で JList に追加されます)

正規表現を取り入れようとしました.split()が、成功していません。*と を使用して構文を試してみましたが、分割する引数が 1 つしかない.ため、特に意図したとおりではないと思います。.split()

それ以外の場合、別の方法は Pattern および Matcher クラスを使用することだと思いますか? しかし、私は適切な手順について本当に曖昧です。

4

3 に答える 3

88

これを行う正規表現を作成できます。

// pattern1 and pattern2 are String objects
String regexString = Pattern.quote(pattern1) + "(.*?)" + Pattern.quote(pattern2);

これはpattern1andpattern2リテラルテキストとして扱い、パターン間のテキストは最初のキャプチャ グループにキャプチャされます。Pattern.quote()正規表現を使用したい場合は削除できますが、削除した場合の保証はありません。

にフラグを追加することで、一致の発生方法をカスタマイズできますregexString

  • Unicode 対応の大文字と小文字を区別しない一致が必要な場合(?iu)は、 の先頭に追加するregexStringか、メソッドPattern.CASE_INSENSITIVE | Pattern.UNICODE_CASEにフラグを指定しPattern.compileます。
  • 2 つの区切り文字列が複数の行にまたがって表示される場合でもコンテンツをキャプチャしたい場合は、(?s)前に を追加するか(.*?)、メソッドにフラグを指定します。"(?s)(.*?)"Pattern.DOTALLPattern.compile

次に、正規表現をコンパイルし、オブジェクトを取得Matcherし、一致を反復処理して、それらを a List(または any Collection、それはあなた次第です) に保存します。

Pattern pattern = Pattern.compile(regexString);
// text contains the full text that you want to extract data
Matcher matcher = pattern.matcher(text);

while (matcher.find()) {
  String textInBetween = matcher.group(1); // Since (.*?) is capturing group 1
  // You can insert match into a List/Collection here
}

テスト コード:

String pattern1 = "hgb";
String pattern2 = "|";
String text = "sdfjsdkhfkjsdf hgb sdjfkhsdkfsdf |sdfjksdhfjksd sdf sdkjfhsdkf | sdkjfh hgb sdkjfdshfks|";

Pattern p = Pattern.compile(Pattern.quote(pattern1) + "(.*?)" + Pattern.quote(pattern2));
Matcher m = p.matcher(text);
while (m.find()) {
  System.out.println(m.group(1));
}

foo上記の方法でbarこの入力の間のテキストを検索するfoo text foo text bar text barと、1 つの一致が得られることに注意してください text foo text 

于 2012-06-29T02:41:53.100 に答える
12

すべてを行うワンライナーを次に示します。

List<String> strings = Arrays.asList( input.replaceAll("^.*?pattern1", "")
    .split("pattern2.*?(pattern1|$)"));

内訳は次のとおりです。

  1. pattern1 までのすべてを削除します (最初の項が空文字列にならないようにする必要があります)。
  2. .*?パターン 2 とパターン 1 (または入力の最後) の間の入力 (貪欲でない) で分割します。
  3. ユーティリティ メソッドArrays.asList()を使用してList<String>

ここにいくつかのテストコードがあります:

public static void main( String[] args ) {
    String input = "abcabc pattern1foopattern2 abcdefg pattern1barpattern2 morestuff";
    List<String> strings = Arrays.asList( input.replaceAll("^.*?pattern1", "").split("pattern2.*?(pattern1|$)"));
    System.out.println( strings);
}

出力:

[foo, bar]
于 2012-06-29T02:41:16.660 に答える
11

これを試して:

String str = "its a string with pattern1 aleatory pattern2 things between pattern1 and pattern2 and sometimes pattern1 pattern2 nothing";
Matcher m = Pattern.compile(
                            Pattern.quote("pattern1")
                            + "(.*?)"
                            + Pattern.quote("pattern2")
                   ).matcher(str);
while(m.find()){
    String match = m.group(1);
    System.out.println(">"+match+"<");
    //here you insert 'match' into the list
}

それは印刷します:

> aleatory <
> and <
> <
于 2012-06-29T02:56:37.117 に答える