正規表現を使用してJavaで値を抽出する


169

大まかな形でいくつかの文字列があります:

[some text] [some number] [some more text]

Java正規表現クラスを使用して、[いくつか]のテキストを抽出したいと思います。

使用したい正規表現を大まかに知っています(ただし、すべての提案を歓迎します)。私が本当に興味を持っているのは、正規表現文字列を取得し、それをソースデータで使用して[some number]の値を生成するJava呼び出しです。

編集:私は単一の[いくつかの番号](基本的には最初のインスタンス)にのみ興味があることを追加する必要があります。ソース文字列は短く、[数]の複数の出現を探すつもりはありません。


11
...そして今、研究に取り掛かっています。私がそれを理解する前に、SOが私に答えを得ることができるかどうか見てみましょう。:-P
クレイグウォーカー

これは、ソフトウェアエンジニアリングの銀行/投資/商社でのインタビューの質問でしたね。:P
ennth

@ennthいいえ、近づきません!それは、小規模ビジネスのWebサイトでのプロダクションコード用でした。
クレイグウォーカー

1
ほんの数日前にJP Morgan Chase Software Engineeringコーディング試験でほぼ同じ質問が寄せられました:P
ennth

回答:


316

完全な例:

private static final Pattern p = Pattern.compile("^([a-zA-Z]+)([0-9]+)(.*)");
public static void main(String[] args) {
    // create matcher for pattern p and given string
    Matcher m = p.matcher("Testing123Testing");

    // if an occurrence if a pattern was found in a given string...
    if (m.find()) {
        // ...then you can use group() methods.
        System.out.println(m.group(0)); // whole matched expression
        System.out.println(m.group(1)); // first expression from round brackets (Testing)
        System.out.println(m.group(2)); // second one (123)
        System.out.println(m.group(3)); // third one (Testing)
    }
}

最初の数を探しているので、次のような正規表現を使用できます。

^\D+(\d+).*

そしてm.group(1)あなたの最初の番号を返します。符号付きの数値にはマイナス記号を含めることができます。

^\D+(-?\d+).*

62
Patterオブジェクトを再利用することを忘れないでください。パターンのコンパイルには膨大な時間がかかります。
Rastislav Komara 2008年

14
同意した。通常、私はパターンをプライベート静的最終パターンとして定義します。パターンPATTERN = Pattern.compile( "..."); しかし、それは私だけです。
Allain Lalonde、

6
単純にパターンp = Pattern.compile( "\\ d +");を使用できます。
javaMan

15
説明なしでこれは悪い答えです。
Martin Spamer、2013年

マッチャーを再利用することもできます。各使用の間にMatcherのreset()メソッドを呼び出します。複数の同時スレッドでマッチャーを共有している場合は、操作を同期する必要があります。
マルケス

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

public class Regex1 {
    public static void main(String[]args) {
        Pattern p = Pattern.compile("\\d+");
        Matcher m = p.matcher("hello1234goodboy789very2345");
        while(m.find()) {
            System.out.println(m.group());
        }
    }
}

出力:

1234
789
2345

この質問では、最初に出現する数値のみを具体的に求めています。
NoBrainer 2015年

34

Allainは基本的にJavaコードを持っているので、それを使用できます。ただし、彼の表現が一致するのは、数字の前に単語文字のストリームが続いている場合のみです。

"(\\d+)"

数字の最初の文字列を見つけることができるはずです。数字の最初の文字列になることが確実な場合は、その前に何があるかを指定する必要はありません。同様に、それが必要でない限り、その後に何があるかを指定することはできません。数値だけが必要で、それが1つ以上の数字の最初の文字列であることが確実な場合は、それで十分です。

スペースでオフセットされることが予想される場合は、指定することでさらに明確になります。

"\\s+(\\d+)\\s+"

良いかもしれません。

3つの部分すべてが必要な場合、これで十分です。

"(\\D+)(\\d+)(.*)"

EDITはアランとジャックによって与えられた式を使用すると、キャプチャするために、数字以外のいくつかのサブセットを指定する必要がありますことを示唆している数字。探している正規表現エンジンを指定\dすると、数字の前のすべてが無視されます。JまたはAの式がパターンに適合する場合、一致全体入力文字列等しくなります。そして、それを指定する理由はありません。それが完全に無視されない場合、それはおそらく完全な一致を遅くします。


Axemansの仮説をテストするには、サンプルテストを実行して、AxemansとA / Jソリューションのパフォーマンスを確認します。
anjanb 2008年

文字列の最初と最後を指定する必要はありませんか?そうでなければ、124xxx123xxxのようなものは彼の構文に適合していなくても一致しますか?または、^と$は暗黙的ですか?
Allain Lalonde、

アライン、あなたも失敗するでしょう。あなたとジャックは、数字以外の文字が数字の前にあると仮定します。彼らはそうするかしないかのどちらかです。その場合、これらの式はいずれもこの行を解析しません。指定どおり繰り返しますが、数字のパターンで十分です。
Axeman、

11

Patternに加えて、Java Stringクラスには、正規表現を使用できるいくつかのメソッドもあります。この場合、コードは次のようになります。

"ab123abc".replaceFirst("\\D*(\\d*).*", "$1")

どこ\\D数字以外の文字があります。


10

Java 1.4以降:

String input = "...";
Matcher matcher = Pattern.compile("[^0-9]+([0-9]+)[^0-9]+").matcher(input);
if (matcher.find()) {
    String someNumberStr = matcher.group(1);
    // if you need this to be an int:
    int someNumberInt = Integer.parseInt(someNumberStr);
}

8

この関数は、文字列からすべての一致するシーケンスを収集します。この例では、文字列からすべての電子メールアドレスを取得します。

static final String EMAIL_PATTERN = "[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
        + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})";

public List<String> getAllEmails(String message) {      
    List<String> result = null;
    Matcher matcher = Pattern.compile(EMAIL_PATTERN).matcher(message);

    if (matcher.find()) {
        result = new ArrayList<String>();
        result.add(matcher.group());

        while (matcher.find()) {
            result.add(matcher.group());
        }
    }

    return result;
}

以下のためmessage = "adf@gmail.com, <another@osiem.osiem>>>> lalala@aaa.pl"には、3つの要素のリストを作成します。


3

次のようなことを試してください:

Pattern p = Pattern.compile("^.+(\\d+).+");
Matcher m = p.matcher("Testing123Testing");

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

3
-1。.+貪欲に文字を消費するため、\d+のみをキャプチャ"3""123"ます。また、文字列リテラル内では、バックスラッシュをエスケープする必要があります(例はコンパイルされません)。
Bart Kiers、2011

3

シンプルなソリューション

// Regexplanation:
// ^       beginning of line
// \\D+    1+ non-digit characters
// (\\d+)  1+ digit characters in a capture group
// .*      0+ any character
String regexStr = "^\\D+(\\d+).*";

// Compile the regex String into a Pattern
Pattern p = Pattern.compile(regexStr);

// Create a matcher with the input String
Matcher m = p.matcher(inputStr);

// If we find a match
if (m.find()) {
    // Get the String from the first capture group
    String someDigits = m.group(1);
    // ...do something with someDigits
}

Utilクラスのソリューション

public class MyUtil {
    private static Pattern pattern = Pattern.compile("^\\D+(\\d+).*");
    private static Matcher matcher = pattern.matcher("");

    // Assumptions: inputStr is a non-null String
    public static String extractFirstNumber(String inputStr){
        // Reset the matcher with a new input String
        matcher.reset(inputStr);

        // Check if there's a match
        if(matcher.find()){
            // Return the number (in the first capture group)
            return matcher.group(1);
        }else{
            // Return some default value, if there is no match
            return null;
        }
    }
}

...

// Use the util function and print out the result
String firstNum = MyUtil.extractFirstNumber("Testing4234Things");
System.out.println(firstNum);

1

StringTokenizerを使用してそれを行うことができます見て

String str = "as:"+123+"as:"+234+"as:"+345;
StringTokenizer st = new StringTokenizer(str,"as:");

while(st.hasMoreTokens())
{
  String k = st.nextToken();    // you will get first numeric data i.e 123
  int kk = Integer.parseInt(k);
  System.out.println("k string token in integer        " + kk);

  String k1 = st.nextToken();   //  you will get second numeric data i.e 234
  int kk1 = Integer.parseInt(k1);
  System.out.println("new string k1 token in integer   :" + kk1);

  String k2 = st.nextToken();   //  you will get third numeric data i.e 345
  int kk2 = Integer.parseInt(k2);
  System.out.println("k2 string token is in integer   : " + kk2);
}

これらの数値データを3つの異なる変数に取り込むため、このデータをコードの任意の場所で使用できます(後で使用するため)


0

どのようにして[^\\d]*([0-9]+[\\s]*[.,]{0,1}[\\s]*[0-9]*).*私はそれが小数部と数字の世話をするだろうと思います。空白を含め,、可能なセパレータとして含めました。私は、浮動小数点数を含む文字列から数値を取得することを試みており、ユーザーが間違えて数値を入力するときに空白を含める可能性があることを考慮しています。


0

java.lang.Stringで利用可能な単純な.split( "REGEXP")メソッドを使用できる場合があります。例えば:

String input = "first,second,third";

//To retrieve 'first' 
input.split(",")[0] 
//second
input.split(",")[1]
//third
input.split(",")[2]

0
Pattern p = Pattern.compile("(\\D+)(\\d+)(.*)");
Matcher m = p.matcher("this is your number:1234 thank you");
if (m.find()) {
    String someNumberStr = m.group(2);
    int someNumberInt = Integer.parseInt(someNumberStr);
}

1
詳細を編集してください。コードのみの回答と「これを試す」の回答は、検索可能なコンテンツが含まれておらず、誰かが「これを試す」必要がある理由を説明していないため、お勧めしません。ここでは、知識のリソースとなるよう努力しています。
ブライアントンプセット-汤莱恩

1
価値を追加せずにずっと前に与えられた正解を繰り返すだけの反対投票
Forage

-1

あなたがファイルから読んでいるなら、これはあなたを助けることができます

              try{
             InputStream inputStream = (InputStream) mnpMainBean.getUploadedBulk().getInputStream();
             BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
             String line;
             //Ref:03
             while ((line = br.readLine()) != null) {
                if (line.matches("[A-Z],\\d,(\\d*,){2}(\\s*\\d*\\|\\d*:)+")) {
                     String[] splitRecord = line.split(",");
                     //do something
                 }
                 else{
                     br.close();
                     //error
                     return;
                 }
             }
                br.close();

             }
         }
         catch (IOException  ioExpception){
             logger.logDebug("Exception " + ioExpception.getStackTrace());
         }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.