- PR -

文字列で、正規表現に一致した部分を配列で取得するには…

投稿者投稿内容
未記入
会議室デビュー日: 2005/07/15
投稿数: 11
投稿日時: 2006-03-17 15:12
いつも、みなさまの記事を拝見させていただき、参考にさせていただいております。

今回、どうしても自分で納得のいかない処理の仕方をしてしまっているため、
みなさんのお知恵をお借りしたいです。

件名にも書きましたが、やりたいことは、
文字列の中から、正規表現に一致する部分を全て抜き出して、配列に形式で取得したいのです。

今のところ、処理自体は、以下のようにして解決しています。
1.正規表現で一致する位置を確認する。
2.正規表現の最後の部分を探して、そこまでの文字列を取得する。
3.1〜2を繰り返して、文字列を最後まで、走査する。

もっとスマートな解法がないか、いろいろ調べたのつもりなのですが、
この方法しか思いつきませんでした。

このような場合に、もっと良い方法があるとか、便利な関数が既に存在するなど、
みなさまのご意見をお聞かせいただけないでしょうか。

よろしくお願いします。
未記入
会議室デビュー日: 2005/07/15
投稿数: 11
投稿日時: 2006-03-17 15:19
追加で、具体的な例を書いておきます。
(現在の作り方)

String regex = "<.*>";
String str = "抜き出さない部分1<抜き出したい部分1>抜き出さない部分2<抜き出したい部分2>";
String[] strs = MyStringUtils.getStrings( str, regex );

MyStringUtilsは、自作のクラスです。
getStringsは、{"<抜き出したい部分1>", "<抜き出したい部分2>"}という形式で作っています。
Edosson
ぬし
会議室デビュー日: 2004/04/30
投稿数: 675
投稿日時: 2006-03-17 15:35
まずは、
引用:

String regex = "<.*>";



引用:

String regex = "<[^<]*>";


に変更してはどうでしょうか。
これで、端っこから順番にマッチさせていくことができるなら、
スマートなループが作れると思います。
paniponi-x
常連さん
会議室デビュー日: 2006/01/14
投稿数: 27
投稿日時: 2006-03-17 15:35
Javaでやるんですよね?
とすると地道に'(',')'とendプロパティを使って開始位置をずらしながら
マッチングを繰り返す方法になると思いますが

引用:

String regex = "<.*>";
String str = "抜き出さない部分1<抜き出したい部分1>抜き出さない部分2<抜き出したい部分2>";



これ、本当に抜き出したい部分だけ取れます?

コード:
<.*?>



でないと、後ろのほうまでマッチが進むと思うんですが。

#PythonとかPerl, Ruby なら一発で全部取れるんですけどねえ。
ゆう
常連さん
会議室デビュー日: 2003/06/27
投稿数: 45
投稿日時: 2006-03-17 15:57
引用:

paniponi-xさんの書き込み (2006-03-17 15:35) より:
Javaでやるんですよね?
とすると地道に'(',')'とendプロパティを使って開始位置をずらしながら
マッチングを繰り返す方法になると思いますが



 Jakarta-OROのPerl5Utilクラスなら、matchメソッドを呼ぶ度に
次の候補から始まります。標準だとMatcher.findメソッドあたり?

 endプロパティを使用せずに、正規表現クラスとループだけで行
けると思います。


[ メッセージ編集済み 編集者: 悠 編集日時 2006-03-17 15:58 ]
paniponi-x
常連さん
会議室デビュー日: 2006/01/14
投稿数: 27
投稿日時: 2006-03-17 16:27
どもです。

引用:

 Jakarta-OROのPerl5Utilクラスなら、matchメソッドを呼ぶ度に
次の候補から始まります。標準だとMatcher.findメソッドあたり?



Jakartaは知らないのでぐぐってドキュメントを見てみましたが、
matchメソッドを呼び出すたびに開始位置がずれるというのは
見つけられませんでした。疑ってるわけではありませんが
ポインタを示していただけませんか?

で、そのドキュメントで見つけたんですが

引用:

grep
public java.lang.String[] grep(java.lang.Object[] search)正規表現にマッチした文字列を文字列の配列として返します。 このメソッドは、Perl の grep のように動作します。 正規表現"a*b"と、文字列のオブジェクト配列[foo, aab, zzz, aaaab] が与えられたとき、[aaa, aaaab]という文字列の配列を返します。
パラメータ:
search - 探索したいオブジェクトの配列
戻り値:
この正規表現にマッチした文字列の値を、 文字列の配列として返します。



これひとつですんじゃいそうな気が。

追記:


Matcher (Java 2 プラットフォーム SE v1.4.0)




引用:

find

public boolean find()

入力シーケンスからこのパターンとマッチする次の部分シーケンスを検索します。

このメソッドは、入力シーケンスの先頭から開始されます。ただし、前回の呼び出しが正常に終了してから正規表現エンジンがリセットされていない場合は、前回のマッチで一致しなかった最初の文字から開始されます。

マッチが成功した場合は、start、end、および group メソッドを使用して詳細情報を取得できます。

戻り値:
入力シーケンスの部分シーケンスがこの正規表現エンジンのパターンとマッチした場合にかぎり、true



というのがありますね。
確かにループ組むだけですみますね。


[ メッセージ編集済み 編集者: paniponi-x 編集日時 2006-03-17 16:33 ]
未記入
会議室デビュー日: 2005/07/15
投稿数: 11
投稿日時: 2006-03-17 16:34
> Edossonさん,paniponi-xさん

すいません。
正規表現間違えていました。

実行確認前に書き込んでしまいました。
String str = "<.*?>";
でないとダメですね。

恥ずかしい限りです。


> 悠さん

ありがとうございます。
Matcher.findなどを、使いながら、作り変えてみます。


皆さんの意見を参考にしながら、作り変えてみます。
Stringクラスのsplit(regex)メソッドも見てみたのですが、Matcherのfind()とend()を繰り返す形式でいいと思いました。

みなさん、適切なアドバイス、ありがとうございました。
想馬
大ベテラン
会議室デビュー日: 2003/05/29
投稿数: 245
お住まい・勤務地: 神奈川・東京
投稿日時: 2006-03-17 16:41
コード:
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public Main() {
        String str = "aaa<111>bbbb<2222>ccc<3333>";
        String pattern = "<([^>]*)>";
        
        String[] array = hoge( str, pattern );
        
        for ( int i = 0; array.length > i; i++ ) {
            System.out.println( array[i] );
        }
    }

    public static void main( String[] args ) {

        new Main();
        
    }
    
    public String[] hoge( String string, String pattern ) {
        
        List list = new ArrayList();
        
        Pattern p = Pattern.compile( pattern );
        Matcher m = p.matcher( string );
        
        while ( m.find() ) {
            list.add( m.group( 1 ) );
        }
        
        String[] array = new String[list.size()];
        list.toArray( array );
        return array;
    }
}


こんな感じになるのかな。

スキルアップ/キャリアアップ(JOB@IT)