정규 표현식을 사용하여 Java에서 값 추출


169

거친 형태의 여러 줄이 있습니다.

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

Java Regex 클래스를 사용하여 [일부 번호]로 텍스트를 추출하고 싶습니다.

나는 어떤 정규 표현식을 사용하고 싶은지 대략 알고 있습니다 (모든 제안을 환영하지만). 내가 정말로 관심이있는 것은 정규식 문자열을 가져와 소스 데이터에 사용하여 [일부 숫자] 값을 생성하는 Java 호출입니다.

편집 : 나는 하나의 [일부 숫자] (기본적으로 첫 번째 인스턴스)에만 관심이 있다고 덧붙여 야합니다. 소스 문자열이 짧고 여러 번 [일부 숫자]를 찾지 않을 것입니다.


11
... 그리고 지금은 연구를 떠납니다. 내가 알아 내기 전에 SO가 나에게 답을 얻을 수 있는지 봅시다. :-P
Craig Walker

이것은 소프트웨어 엔지니어링에 대한 은행 / 투자 / 무역 회사의 인터뷰 질문이 아니 었습니까? : P
ennth

@ennth 아니, 심지어 가까이! 그것은 작은 달 웹 사이트에서 생산 코드를위한 것이었다.
Craig Walker

1
잘 며칠 전에 JP Morgan Chase Software Engineering 코딩 시험에서 거의 동일한 정확한 질문을
받았습니다

답변:


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

14
동의했다. 일반적으로 패턴을 개인 정적 최종 패턴으로 정의합니다. PATTERN = Pattern.compile ( "..."); 그러나 그것은 단지 나입니다.
Allain Lalonde

6
패턴 p = Pattern.compile ( "\\ d +");
javaMan

15
설명없이 이것은 나쁜 대답입니다.
Martin Spamer

Matcher를 재사용 할 수도 있습니다. 매번 사용할 때마다 Matcher의 reset () 메소드를 호출하십시오. 여러 동시 스레드에서 매처를 공유하는 경우 조작을 동기화해야합니다.
Marquez

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 2016 년

34

Allain은 기본적으로 Java 코드를 가지고 있으므로 사용할 수 있습니다. 그러나 숫자 앞에 단어 문자 만 오는 경우 에만 그의 표현이 일치 합니다 .

"(\\d+)"

첫 번째 숫자 문자열을 찾을 수 있어야합니다. 첫 번째 숫자 문자열이 확실하다면 이전의 내용을 지정할 필요가 없습니다. 마찬가지로, 원하는 경우를 제외하고 그 이후의 내용을 지정하는 데 사용할 수 없습니다. 숫자를 원하고 하나 이상의 숫자로 된 첫 번째 문자열이 확실하다면 이것이 전부입니다.

공백으로 오프셋 될 것으로 예상하면 더 명확하게 지정할 수 있습니다.

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

더 좋을 수도 있습니다.

세 부분이 모두 필요한 경우 다음을 수행하십시오.

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

편집 Allain이 잭에 의해 주어진 표현은 캡처하기 위해 비 숫자의 일부 하위 집합을 지정해야하는 것이 좋습니다 자리 . 당신이 찾고있는 정규식 엔진에 말하면 \d숫자 앞의 모든 것을 무시합니다. J 또는 A의 발현이 경우 에 맞는 당신의 패턴을, 다음 전체 경기는 동일 입력 문자열을 . 그리고 그것을 지정할 이유가 없습니다. 완전히 무시하지 않으면 깔끔한 일치 속도가 느려질 수 있습니다.


샘플 테스트를 실행하고 그의 vs. A / J 솔루션의 성능을 확인하여 Axemans의 가설을 테스트 할 수 있습니다.
anjanb

문자열의 시작과 끝을 지정할 필요가 없습니다. 그렇지 않으면 124xxx123xxx와 같은 것이 구문에 맞지 않더라도 일치합니까? 아니면 ^와 $가 암시 적입니까?
Allain Lalonde

Allain, 당신도 실패 할 것입니다. 귀하와 Jack은 숫자가 아닌 문자가 숫자보다 우선한다고 가정합니다. 그들은하거나하지 않습니다. 이 경우이 식 중 어느 것도이 줄을 구문 분석하지 않습니다. 지정된대로 숫자 패턴이 충분 하다는 것을 반복합니다 .
Axeman

11

Java String 클래스에는 Pattern 외에도 정규 표현식에서 작동 할 수있는 몇 가지 메소드가 있으며,이 경우 코드는 다음과 같습니다.

"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. .+탐욕스럽게 캐릭터를 소비 하기 때문에 from \d+만 캡처합니다 . 또한 문자열 리터럴 내에서 백 슬래시를 이스케이프 처리해야합니다 (예제가 컴파일되지 않음). "3""123"
Bart Kiers

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);
}

이 숫자 데이터를 세 개의 다른 변수로 가져 오기 때문에 코드의 어느 곳에서나이 데이터를 사용할 수 있습니다 (추가 사용).


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
자세한 내용으로 편집하십시오. 검색 가능한 콘텐츠가 포함되어 있지 않으며 누군가 "이 작업을 시도해야하는 이유"를 설명하지 않기 때문에 코드 전용 및 "이것을 시도하십시오"답변은 권장되지 않습니다. 우리는 지식의 원천이되기 위해 노력합니다.
Brian Tompsett-汤 莱恩

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.