정규식을 사용하여 하위 문자열을 추출하는 방법


382

두 개의 작은 따옴표가있는 문자열이 있습니다 '. 작은 따옴표 사이에는 내가 원하는 데이터가 있습니다.

다음 텍스트에서 "원하는 데이터"를 추출하기 위해 정규식을 작성하려면 어떻게해야합니까?

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
젠장 .. 난 항상 욕심없는 수정 자 잊어 : (
Mihai Toader

33
하나 이상의 발생을 예상 할 경우 "if"를 "while"로 바꾸십시오
OneWorld

14
이 코드 샘플이 작동하려면 matcher.find ()가 필요합니다. 이 메소드를 호출하지 않으면 matcher.group (1)이 호출 될 때 "No match found"예외가 발생합니다.
rexford

25
@mFontoura group (0)은 외부 ''와의 완전한 일치를 반환합니다. group (1)은 ''없이 ''사이에있는 것을 반환합니다.
tagy22

6
@Larry 이것은 늦은 답변이지만? 이 경우 욕심없는 수정 자이므로 가능한 한 많은 문자를 일치시키는 대신 this 'is' my 'data' with quotes일찍 중지하고 반환 하므로 기본 동작입니다. isis' my 'data
Timekiller

68

이를 위해 정규식이 필요하지 않습니다.

프로젝트에 Apache Commons lang을 추가 한 후 ( http://commons.apache.org/proper/commons-lang/ ) 다음을 사용하십시오.

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

12
소프트웨어 배포 방법을 고려해야합니다. 웹 스타트와 같은 것이면 Apache Commons를 추가 하여이 기능을 사용하는 것이 현명하지 않습니다. 그러나 아닐 수도 있습니다. 아파치 커먼즈는 더 많은 것을 제공합니다. 힘든 일이라 할지라도 정규 표현식을 아는 것이 좋지만, 언제 사용해야하는지주의해야합니다. 정규식은 읽기, 쓰기 및 디버그가 실제로 어려울 수 있습니다. 이것을 사용하는 문맥이 더 나은 해결책 일 수 있습니다.
Beothorn

3
때로는 StringUtils가 이미 존재하는 경우이 솔루션은 훨씬 깨끗하고 읽기 쉽습니다.
Gábor Nagy

7
5 마일 (1 년에 한 번만 여행하는 경우)을 운전하기 위해 자동차를 구입하는 것과 같습니다.
prayagupd

부분 문자열은 특정 문자열이나 값을 찾는 반면 정규 표현식은 형식을 찾습니다. 점점 더 역동적입니다. 특별한 값 대신 패턴을 찾고 있다면 정규 표현식이 필요합니다.
burakhan alkan

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 (매처 그룹 (0)); <--- 제로 기반 인덱스
nclord

4
그룹 (0)은 특별한 의미를 지니고 있습니다. 캡처 그룹은 인덱스 그룹 (1)에서 시작합니다 (즉, 그룹 (1)이 정답). "캡처 그룹은 1부터 시작하여 왼쪽에서 오른쪽으로 색인됩니다. 그룹 0은 전체 패턴을 나타냅니다."-출처 : docs.oracle.com/javase/8/docs/api/java/util/regex/…
Apriori

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
그래서 읽기 쉬운 해결책, 그것이 사람들이 스칼라를 좋아하는 이유입니다. :)
prayagupd

3
.split('\'').get(2)Java에서 그 정도 또는 그 정도가 아닌 이유는 무엇 입니까? 나는 그것이 읽을 수있는 해결책이라고 생각하면 뇌 스캔을 받아야 할 수도 있다고 생각합니다. 누군가가 나에게 코드 골프를하려고하는 것처럼 보입니다.
ArtOfWarfare

7
String dataIWant = mydata.replaceFirst(".*'(.*?)'.*", "$1");

4

자바 스크립트에서와 같이 :

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

실제 정규 표현식은 다음과 같습니다. /'([^']+)'/

욕심없는 수정자를 사용하면 (다른 게시물에 따라) 다음과 같습니다.

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

더 깨끗합니다.


2

스칼라에서

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의 두 인스턴스 사이에 중첩 된 String을 가져옵니다 .

시작 부분 문자열과 끝 부분 문자열이 다른 경우 다음 오버로드 된 메소드를 사용하십시오.

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

두 문자열 사이에 중첩 된 문자열을 가져옵니다.

일치하는 부분 문자열의 모든 인스턴스를 원하면

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

Apache.Commons 추가pom.xml 에 종속 항목

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

그리고 아래 코드가 작동합니다.

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

0

그룹 (1)이 어떻게 작동하지 않았는지 몇 가지. URL 버전을 찾기 위해 group (0)을 사용했습니다.

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.