正規表現を使用して部分文字列を抽出する方法


382

文字が2つの一重引用符で囲まれた文字列があります'。単一引用符の間には、必要なデータがあります。

次のテキストから「欲しいデータ」を抽出する正規表現をどのように書くことができますか?

mydata = "some string with 'the data i want' inside";

回答:


569

一重引用符の間の部分が必要であると仮定して、この正規表現をMatcher:で使用します

"'(.*?)'"

例:

String mydata = "some string with 'the data i want' inside";
Pattern pattern = Pattern.compile("'(.*?)'");
Matcher matcher = pattern.matcher(mydata);
if (matcher.find())
{
    System.out.println(matcher.group(1));
}

結果:

私が欲しいデータ

12
くそー

33
複数の発生が予想される場合は、「if」を「while」に置き換えます
OneWorld

14
このコードサンプルが機能するには、matcher.find()が必要です。このメソッドの呼び出しに失敗すると、matcher.group(1)が呼び出されたときに「一致が見つかりません」という例外が発生します。
レックスフォード2014

25
@mFontoura group(0)は、外側の ''との完全な一致を返します。group(1)は、 ''の間にない ''の間にあるものを返します。
tagy22

6
@ラリーこれは遅い返事ですが?この場合、貪欲でない修飾子です。そのため、可能な限り多くの文字を照合してthis 'is' my 'data' with quotes返すのではisなく、早期に停止して戻りis' my 'dataます。これはデフォルトの動作です。
Timekiller 2016

68

これには正規表現は必要ありません。

Apache Commons langをプロジェクト(http://commons.apache.org/proper/commons-lang/)に追加してから、次を使用します。

String dataYouWant = StringUtils.substringBetween(mydata, "'");

12
ソフトウェアの配布方法を考慮する必要があります。Webstartのようなものである場合、この1つの機能を使用するためだけにApacheコモンズを追加することは賢明ではありません。しかし、そうではないかもしれません。Apacheコモンズの他にも、提供することがたくさんあります。正規表現を知るのは大変ですが、いつ使用するかには注意が必要です。正規表現は、読み取り、書き込み、デバッグが非常に難しい場合があります。これを使用するいくつかのコンテキストを考えると、より良い解決策になる可能性があります。
Beothorn、2015

3
StringUtilsがすでに存在している場合もありますが、その場合、このソリューションはよりクリーンで読みやすくなります。
ガーボル・ナジ

7
車を購入して5マイル移動するようなものです(1年に1回しか移動しない場合)。
prayagupd 2017年

部分文字列は特定の文字列または値を探しますが、正規表現は形式を探します。それはますますダイナミックです。特別な値ではなくパターンを探している場合は、正規表現が必要です。
ブラハンアルカン2017

14
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile(".*'([^']*)'.*");
        String mydata = "some string with 'the data i want' inside";

        Matcher matcher = pattern.matcher(mydata);
        if(matcher.matches()) {
            System.out.println(matcher.group(1));
        }

    }
}

2
System.out.println(matcher.group(0)); <---ゼロベースのインデックス
nclord

4
いいえ。group(0)には特別な意味があります。キャプチャグループはインデックスgroup(1)から始まります(つまり、group(1)が正解です)。「キャプチャグループは1から始まり、左から右にインデックス化されているグループゼロがパターン全体示している。」 -出典:docs.oracle.com/javase/8/docs/api/java/util/regex/...
アプリオリ

12

これには簡単なワンライナーがあります:

String target = myData.replaceAll("[^']*(?:'(.*?)')?.*", "$1");

一致するグループをオプションにすることで、その場合は空白を返すことで、引用符が見つからないことにも対応できます。

ライブデモをご覧ください。


10

複数の引用符で囲まれた文字列を簡単に処理する正規表現なしのソリューションであるScalaもチェックしたためです。

val text = "some string with 'the data i want' inside 'and even more data'"
text.split("'").zipWithIndex.filter(_._2 % 2 != 0).map(_._1)

res: Array[java.lang.String] = Array(the data i want, and even more data)

4
とても読みやすいソリューション、それが人々が私が
信じる

3
なぜ.split('\'').get(2)Javaでその程度まで、または何かしませんか?それが読みやすい解決策だと思うなら、あなたは脳スキャンをする必要があるかもしれないと思います-誰かが私にコードゴルフをしようとしたようです。
ArtOfWarfare 2017


4

JavaScriptのように:

mydata.match(/'([^']+)'/)[1]

実際の正規表現は: /'([^']+)'/

(別の投稿に従って)貪欲でない修飾子を使用すると、次のようになります:

mydata.match(/'(.*?)'/)[1]

きれいです。


2

Scalaでは、

val ticks = "'([^']*)'".r

ticks findFirstIn mydata match {
    case Some(ticks(inside)) => println(inside)
    case _ => println("nothing")
}

for (ticks(inside) <- ticks findAllIn mydata) println(inside) // multiple matches

val Some(ticks(inside)) = ticks findFirstIn mydata // may throw exception

val ticks = ".*'([^']*)'.*".r    
val ticks(inside) = mydata // safe, shorter, only gets the first set of ticks


1

Apache Commons Langは、java.lang APIのヘルパーユーティリティのホストを提供します。特に、文字列操作メソッドです。あなたの場合、開始部分文字列と終了部分文字列は同じなので、次の関数を呼び出すだけです。

StringUtils.substringBetween(String str, String tag)

同じStringの2つのインスタンスの間にネストされているStringを取得します。

開始部分文字列と終了部分文字列が異なる場合は、次のオーバーロードメソッドを使用します。

StringUtils.substringBetween(String str, String open, String close)

2つの文字列の間にネストされている文字列を取得します。

一致する部分文字列のすべてのインスタンスが必要な場合は、次を使用します。

StringUtils.substringsBetween(String str, String open, String close)

開始タグと終了タグで区切られた部分文字列の文字列を検索し、一致するすべての部分文字列を配列返します

問題の例では、一致する部分文字列のすべてのインスタンスを取得します

String[] results = StringUtils.substringsBetween(mydata, "'", "'");

0

あなたが使用する場合、これを使用してwhileループを配列内のすべての一致する部分文字列を格納できます

if (matcher.find()) { System.out.println(matcher.group(1)); }

あなたは一致部分文字列を取得するので、これを使用してすべての一致部分文字列を取得できます

Matcher m = Pattern.compile("[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+").matcher(text);
   // Matcher  mat = pattern.matcher(text);
    ArrayList<String>matchesEmail = new ArrayList<>();
        while (m.find()){
            String s = m.group();
            if(!matchesEmail.contains(s))
                matchesEmail.add(s);
        }

    Log.d(TAG, "emails: "+matchesEmail);

0

pom.xmlにapache.commons依存関係を追加します

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.3.2</version>
</dependency>

そして以下のコードは動作します。

StringUtils.substringBetween(String mydata, String "'", String "'")

0

グループ(1)が私にとってどのように機能しなかったか。group(0)を使用してURLバージョンを見つけました。

Pattern urlVersionPattern = Pattern.compile("\\/v[0-9][a-z]{0,1}\\/");
Matcher m = urlVersionPattern.matcher(url);
if (m.find()) { 
    return StringUtils.substringBetween(m.group(0), "/", "/");
}
return "v0";
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.