정규식에서 단어 경계는 무엇입니까?


137

Java 1.6에서 Java 정규식을 사용하고 있으며 (다른 목적 중에서 숫자 출력을 구문 분석하기 위해) \b" 정확한 단어 경계" 의 정확한 정의를 찾을 수 없습니다 . 나는 -12"정수 단어"(와 일치 \b\-?\d+\b) 라고 가정 했지만 이것이 작동하지 않는 것 같습니다. 공백으로 구분 된 숫자를 일치시키는 방법을 알고 감사합니다.

예:

Pattern pattern = Pattern.compile("\\s*\\b\\-?\\d+\\s*");
String plus = " 12 ";
System.out.println(""+pattern.matcher(plus).matches());
String minus = " -12 ";
System.out.println(""+pattern.matcher(minus).matches());
pattern = Pattern.compile("\\s*\\-?\\d+\\s*");
System.out.println(""+pattern.matcher(minus).matches());

이것은 다음을 반환합니다.

true
false
true

입력 및 예상 출력으로 작은 예제를 게시 할 수 있습니까?
Brent Writes Code

예제 패턴 패턴 = Pattern.compile ( "\\ s * \\ b \\-? \\ d + \\ s *"); 문자열 플러스 = "12"; System.out.println ( ""+ pattern.matcher (plus) .matches ()); 문자열 빼기 = "-12"; System.out.println ( ""+ pattern.matcher (빼기) .matches ()); pattern = Pattern.compile ( "\\ s * \\-? \\ d + \\ s *"); System.out.println ( ""+ pattern.matcher (빼기) .matches ()); 제공합니다 : true false true
peter.murray.rust

답변:


97

단어 경계가 대부분 정규식 방언하는 사이에 위치 인 \w\W그 단어의 문자로 시작하거나 (각각) 끝나는 경우 문자열 (단어가 아닌 문자) 또는 시작 또는 끝 ( [0-9A-Za-z_]).

따라서 문자열 "-12"에서 1 앞뒤에 일치합니다. 대시는 단어 문자가 아닙니다.


35
Correctamundo. 한쪽 에 있고 다른쪽에 있거나 위치가 문자열의 시작 또는 끝인 \b경우 일치하는 너비가 0 인 어설 션입니다 . 는 "식별자"문자 (숫자 및 밑줄)로 임의로 정의되며 영어에는 특히 유용하지 않습니다. \w\W\w
hobbs

100 % 정확합니다. 귀하의 의견에 대해서만 사과를 드려 죄송합니다. 답변을보기 전에 제출을 누르십시오.
Brent Writes Code

5
이해를 위해 ( , 등을 사용 \bhello\b하지 않고 정규식을 다시 작성할 수 있습니까? \b\w\W
David Portabella

5
Sort :: 단 (^|\W)hello($|\W), 전후에 단어가 아닌 문자를 캡처하지 않으므로 (^|(?<=\W))hello($|(?=\W))lookahead / lookbehind 어설 션을 사용하는 것과 비슷 합니다.
brianary

6
@brianary 약간 더 간단합니다 : (?<!\w)hello(?!\w).
David Knipe

28

단어 경계는 다음 세 위치 중 하나에서 발생할 수 있습니다.

  1. 문자열의 첫 번째 문자 앞에 첫 번째 문자가 단어 문자 인 경우
  2. 문자열의 마지막 문자 다음에 마지막 문자가 단어 문자 인 경우
  3. 문자열에서 두 문자 사이에서 하나는 단어 문자이고 다른 하나는 단어 문자가 아닙니다.

단어 문자는 영숫자입니다. 빼기 부호는 아닙니다. 정규식 튜토리얼 에서 가져 왔습니다 .


21

정규 표현식을 배우는 과정에서 나는 메타 문자에 정말로 빠져 들었습니다 \b. 나는 " 그것이 무엇인지, 그것이 무엇인지 반복적 으로 " 스스로 묻고있는 동안 그 의미를 이해하지 못했습니다 . 웹 사이트 를 사용하여 몇 번 시도한 후 , 나는 단어의 모든 시작과 단어 끝에 분홍색 세로 대시를 보았습니다. 그 당시 그 의미를 잘 알았습니다. 이제 정확하게 단어 \w경계입니다. 입니다.

나의 견해는 단지 엄청나게 이해 지향적 인 것입니다. 그 뒤에 논리는 다른 답변에서 검사해야합니다.

여기에 이미지 설명을 입력하십시오


3
단어 경계 란 무엇이고 어떻게 일치하는지 이해하기에 매우 좋은 사이트
vsingh

2
이 게시물은 말하지 않고 보여줄만한 가치가 있습니다. 그림은 천 단어의 가치가 있습니다.
M_M

13

단어 경계는 단어 문자가 앞에오고 하나가 뒤에 오지 않거나 단어가 뒤에오고 1이 앞에 오지 않는 위치입니다.


8

나는 \b실제로 어떤 스타일의 정규 표현식 경계 에 대해 이야기 합니다 .

짧은 이야기는 조건부라는 것 입니다. 그들의 행동은 그들이 무엇을하고 있는지에 달려 있습니다.

# same as using a \b before:
(?(?=\w) (?<!\w)  | (?<!\W) )

# same as using a \b after:
(?(?<=\w) (?!\w)  | (?!\W)  )

때때로 그것은 당신이 원하는 것이 아닙니다. 정교화에 대한 다른 답변을 참조하십시오.


7

Alan Moore 의 답변 을 설명하고 싶습니다

단어 경계는 단어 문자가 앞에 오며 그 뒤에는 하나가 오지 않거나 단어가 뒤에오고 하나가 앞에 오는 위치입니다.

내가 문자열이 "이것은 가정 C t을, 그리고 그녀의 wesome", 그리고이 모든 사건 (들) 문자 'A'이 편지가 존재하는 경우에만 대체 하죠 "단어의 경계" , 즉 '고양이'안의 글자 는 교체하지 않아야합니다.a

나는 (에서 정규식 수행 할 수 있습니다 그래서 파이썬 으로)

re.sub("\ba","e", myString.strip())대체 // ae

출력이 될 수 있도록이다 ec를 t 차 그녀의 wesomeee


5

즉 원하는 텍스트를 검색 할 때 내가 더 악화 문제로 실행 .NET, C++, C#, 및C . 컴퓨터 프로그래머는 정규 표현식을 작성하기 어려운 언어의 이름을 지정하는 것보다 더 잘 알고 있다고 생각합니다.

어쨌든, 이것은 내가 찾은 것입니다 (대부분 훌륭한 사이트 인 http://www.regular-expressions.info 에서 요약 됩니다) : 대부분의 정규 표현식에서 짧은 문자 클래스와 일치하는 문자 \w는 단어 경계에 의해 단어 문자로 취급되는 문자. Java는 예외입니다. Java는 유니 코드를 지원 \b하지만 지원 하지는 않습니다 \w. (당시에는 그만한 이유가 있다고 확신합니다).

\w"단어 문자"를 의미합니다. 항상 ASCII 문자와 일치합니다 [A-Za-z0-9_]. 밑줄과 숫자가 포함되어 있음을 주목하십시오 (단, 대시는 아님). 유니 코드를 지원 \w하는 대부분의 특징에는 다른 스크립트의 많은 문자가 포함됩니다. 어떤 문자가 실제로 포함되는지에 대해 많은 불일치가 있습니다. 알파벳 문자 및 표의 문자와 숫자가 일반적으로 포함됩니다. 밑줄 및 숫자 이외의 숫자 기호 이외의 커넥터 문장 부호는 포함되거나 포함되지 않을 수 있습니다. XML Schema 및 XPath는의 모든 기호를 포함합니다 \w. 그러나 Java, JavaScript 및 PCRE는 ASCII 문자 만와 일치합니다 \w.

대한 정규식 검색을 자바 기반 이유는 C++, C#또는 .NET(당신이 기간 흑자를 탈출 기억 경우에도)에 의해 망했다\b .

참고 : 문장의 끝에 마침표를 쓴 후 누군가가 공백을 넣지 않는 경우와 같이 텍스트의 실수에 대해 어떻게 해야할지 잘 모르겠습니다. 나는 그것을 허용했지만 그것이 반드시 옳은 일인지 확실하지 않습니다.

어쨌든 Java에서 이상한 이름의 언어에 대한 텍스트를 검색하는 경우 \b공백 및 문장 부호 지정 전후 문자 로 대체해야합니다 . 예를 들면 다음과 같습니다.

public static String grep(String regexp, String multiLineStringToSearch) {
    String result = "";
    String[] lines = multiLineStringToSearch.split("\\n");
    Pattern pattern = Pattern.compile(regexp);
    for (String line : lines) {
        Matcher matcher = pattern.matcher(line);
        if (matcher.find()) {
            result = result + "\n" + line;
        }
    }
    return result.trim();
}

그런 다음 테스트 또는 주요 기능에서 :

    String beforeWord = "(\\s|\\.|\\,|\\!|\\?|\\(|\\)|\\'|\\\"|^)";   
    String afterWord =  "(\\s|\\.|\\,|\\!|\\?|\\(|\\)|\\'|\\\"|$)";
    text = "Programming in C, (C++) C#, Java, and .NET.";
    System.out.println("text="+text);
    // Here is where Java word boundaries do not work correctly on "cutesy" computer language names.  
    System.out.println("Bad word boundary can't find because of Java: grep with word boundary for .NET="+ grep("\\b\\.NET\\b", text));
    System.out.println("Should find: grep exactly for .NET="+ grep(beforeWord+"\\.NET"+afterWord, text));
    System.out.println("Bad word boundary can't find because of Java: grep with word boundary for C#="+ grep("\\bC#\\b", text));
    System.out.println("Should find: grep exactly for C#="+ grep("C#"+afterWord, text));
    System.out.println("Bad word boundary can't find because of Java:grep with word boundary for C++="+ grep("\\bC\\+\\+\\b", text));
    System.out.println("Should find: grep exactly for C++="+ grep(beforeWord+"C\\+\\+"+afterWord, text));

    System.out.println("Should find: grep with word boundary for Java="+ grep("\\bJava\\b", text));
    System.out.println("Should find: grep for case-insensitive java="+ grep("?i)\\bjava\\b", text));
    System.out.println("Should find: grep with word boundary for C="+ grep("\\bC\\b", text));  // Works Ok for this example, but see below
    // Because of the stupid too-short cutsey name, searches find stuff it shouldn't.
    text = "Worked on C&O (Chesapeake and Ohio) Canal when I was younger; more recently developed in Lisp.";
    System.out.println("text="+text);
    System.out.println("Bad word boundary because of C name: grep with word boundary for C="+ grep("\\bC\\b", text));
    System.out.println("Should be blank: grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));
    // Make sure the first and last cases work OK.

    text = "C is a language that should have been named differently.";
    System.out.println("text="+text);
    System.out.println("grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));

    text = "One language that should have been named differently is C";
    System.out.println("text="+text);
    System.out.println("grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));

    //Make sure we don't get false positives
    text = "The letter 'c' can be hard as in Cat, or soft as in Cindy. Computer languages should not require disambiguation (e.g. Ruby, Python vs. Fortran, Hadoop)";
    System.out.println("text="+text);
    System.out.println("Should be blank: grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));

추신 : 정규식 세계가 매우 비참한 http://regexpal.com/에 감사합니다 !


왜 내가 일치하지 않는지 이해하려고 노력 C#했지만 지금은 더 명확합니다
Mugoma J. Okomba

4

경계 조건에 대한 설명서를 확인하십시오.

http://java.sun.com/docs/books/tutorial/essential/regex/bounds.html

이 샘플을 확인하십시오.

public static void main(final String[] args)
    {
        String x = "I found the value -12 in my string.";
        System.err.println(Arrays.toString(x.split("\\b-?\\d+\\b")));
    }

인쇄 할 때 출력은 다음과 같습니다.

[문자열에서-값을 찾았습니다.]

이것은 "-"문자가 단어 문자로 간주되지 않기 때문에 단어의 경계에있는 것으로 선택되지 않음을 의미합니다. @brianary가 나를 펀치로 이길 것 같아서 투표권을 얻습니다.


2

단어 경계 \ b는 한 단어는 단어 문자이고 다른 단어는 단어가 아닌 문자 여야합니다. 음수에 대한 정규식은

--?\b\d+\b

작동 데모 확인


1

나는 당신의 문제가 -단어가 아닌 사실 때문이라고 생각합니다 . 따라서 단어 경계는- . 단어 경계는 문자열에서 첫 번째 및 마지막 단어 문자 앞과 단어 문자 앞 또는 단어가 아닌 문자 앞과 반대 위치에 일치합니다. 또한 단어 경계는 너비가 0입니다.

가능한 대안 중 하나는

(?:(?:^|\s)-?)\d+\b

이것은 공백 문자와 선택적인 대시로 시작하고 단어 경계에서 끝나는 모든 숫자와 일치합니다. 또한 문자열의 시작 부분에서 시작하는 숫자와 일치합니다.


0

마지막 일치 또는 문자열의 시작 또는 끝의 경계 (즉, 문자 뒤)입니다.


1
당신은 생각하고 있습니다 \G: \A첫 번째 일치 시도에서 문자열의 시작과 일치합니다 (예 :). 그 후에는 이전 경기가 끝난 위치와 일치합니다.
Alan Moore

0

당신이 \\b(\\w+)+\\b그것을 사용할 때 단어 문자 만 포함하는 단어와 정확히 일치하는 것을 의미합니다([a-zA-Z0-9])

예를 들어, 설정에 대한 귀하의 경우 \\b정규 표현식의 시작에서 받아 들일 것이다 -12(공간)하지만 다시는 허용하지 않습니다 -12(공백없이)

내 말을 지원하기 위해 참조 : https://docs.oracle.com/javase/tutorial/essential/regex/bounds.html

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.