답변:
가장 중요한 부분은 개념입니다. 빌딩 블록의 작동 방식을 이해하면 구문의 차이는 가벼운 방언에 지나지 않습니다. 정규식 엔진의 구문 위에있는 레이어는 사용중인 프로그래밍 언어의 구문입니다. Perl과 같은 언어는 이러한 복잡한 문제를 대부분 제거하지만 C 프로그램에서 정규식을 사용하는 경우 다른 고려 사항을 염두에 두어야합니다.
정규식을 원하는대로 혼합하고 일치시킬 수있는 빌딩 블록으로 생각하면 자신의 패턴을 작성하고 디버그하는 방법과 다른 사람이 작성한 패턴을 이해하는 방법을 배우는 데 도움이됩니다.
개념 상 가장 간단한 정규식은 리터럴 문자입니다. 패턴 N
은 문자 'N'과 일치합니다.
서로 옆에있는 정규식은 시퀀스와 일치합니다. 예를 들어, 패턴 Nick
은 시퀀스 'N', 'i', 'c', 'k'순으로 일치합니다.
grep
평범한 문자열을 검색하는 경우에도 유닉스를 사용해 본 적이 있다면 이미 정규 표현식을 사용하고있는 것입니다! ( re
에서는 grep
정규 표현식을 의미합니다.)
약간의 복잡성을 추가하면 'Nick'또는 'nick'과 pattern을 일치시킬 수 있습니다 [Nn]ick
. 대괄호로 묶인 부분은 문자 클래스 이므로 동봉 된 문자 중 하나와 정확히 일치합니다. 문자 클래스에서 범위를 사용할 수도 있으므로 [a-c]
'a'또는 'b'또는 'c'와 일치합니다.
패턴 .
은 특별합니다. 리터럴 점만 일치시키기보다는 모든 문자 † 와 일치 합니다 . 실제로 큰 문자 클래스와 개념적으로 같습니다 [-.?+%$A-Za-z0-9...]
.
캐릭터 클래스를 메뉴로 생각하십시오. 하나만 선택하십시오.
를 사용하면 .
입력 내용을 많이 절약 할 수 있으며 일반적인 패턴에 대한 다른 바로 가기가 있습니다. 숫자를 맞추고 싶다고 가정 해보십시오 [0-9]
. 숫자는 자주 일치하는 대상이므로 바로 가기를 사용할 수 있습니다 \d
. 다른 \s
문자 는 (공백) 및 \w
(단어 문자 : 영숫자 또는 밑줄)입니다.
대문자 변형은 보완이므로 예를 들어 공백이 아닌 문자 \S
와 일치합니다 .
여기에서 수량 자로 패턴의 일부를 반복 할 수 있습니다 . 예를 들어, 한정자는 서브 패턴을 수정하는 서브 패턴을 선택적으로 만들기 ab?c
때문에 패턴 은 'abc'또는 'ac'와 일치 ?
합니다. 다른 정량자는
*
(0 회 이상)+
(한 번 이상){n}
(정확히 n 번){n,}
(최소 n 회){n,m}
( n 회 이상 m 회 이하)이 블록 중 일부를 조합하면 패턴 [Nn]*ick
이
첫 번째 경기는 중요한 교훈을 보여줍니다. *
항상 성공합니다! 모든 패턴은 0 번 일치 할 수 있습니다.
몇 가지 다른 유용한 예 :
[0-9]+
(및 동등한 \d+
)은 음이 아닌 정수와 일치합니다.\d{4}-\d{2}-\d{2}
2019-01-01 형식의 날짜와 일치수량자는 패턴을 바로 왼쪽으로 수정합니다. 0abc+0
'0abc0', '0abcabc0'등과 일치 할 것으로 예상 할 수 있지만 플러스 수량 화기 바로 왼쪽의 패턴 은 c
입니다. 이는 0abc+0
'0abc0', '0abcc0', '0abccc0'등과 일치 한다는 의미 입니다.
하나 이상의 'abc'시퀀스를 끝에 0과 일치 시키려면을 사용하십시오 0(abc)+0
. 괄호는 단위로 수량화 할 수있는 하위 패턴을 나타냅니다. 정규식 엔진이 괄호로 묶은 그룹과 일치하는 입력 텍스트 부분을 저장하거나 "캡처"하는 것도 일반적입니다. 이 방법으로 비트를 추출하면 인덱스를 계산하는 것보다 훨씬 유연하고 오류가 적습니다 substr
.
이전에는 '닉'또는 '닉'과 일치하는 방법을 보았습니다. 다른 하나는에서와 같이 교대로 있습니다 Nick|nick
. 교대에는 왼쪽의 모든 것과 오른쪽의 모든 것이 포함됩니다. 의 범위를 제한하기 위해 괄호를 그룹화 사용 |
, 예를 , (Nick|nick)
.
또 다른 예를 들어, 당신은 동등하게 쓸 수 [a-c]
와 같은 a|b|c
, 그러나 많은 구현 대안 1보다 큰 길이를 가질 것으로 가정하기 때문에이 가능성이 최적이 될 것입니다.
일부 문자는 서로 일치하지만 다른 문자는 특별한 의미를 갖습니다. 패턴 \d+
이 백 슬래시와 소문자 D, 더하기 부호와 일치하지 않습니다.이를 얻으려면을 사용 \\d\+
합니다. 백 슬래시는 다음 문자에서 특별한 의미를 제거합니다.
정규식 수량자는 탐욕 스럽습니다. 즉, 전체 패턴을 성공적으로 일치시키면서 가능한 한 많은 텍스트를 일치시킵니다.
예를 들어 입력이
"안녕하세요."그녀는 "어떻게 지내?"
".+"
'Hello'만 일치 할 것으로 예상 할 수 있으며 'Hello'에서 'you?'까지 일치한다는 것을 알면 놀라게됩니다.
욕심 많은 것에서 조심스럽게 생각할 수있는 것으로 바꾸려면 ?
수량 자에 여분 을 더하십시오. 이제 \((.+?)\)
질문의 예가 어떻게 작동 하는지 이해했습니다 . 리터럴 왼쪽 괄호, 하나 이상의 문자 순서 및 오른쪽 괄호로 끝나는 순서와 일치합니다.
입력이 '(123) (456)'이면 첫 번째 캡처는 '123'입니다. 욕심없는 정량자는 나머지 패턴이 가능한 빨리 일치하기를 원합니다.
(혼란에 관해서는, 나는 ((.+?))
같은 일을 할 정규식 방언을 모른다 . 나는 어딘가에서 전송에서 무언가가 잃어버린 것 같다.)
특수 패턴 ^
을 사용 하여 입력 시작 부분 $
에만 일치시키고 끝 부분에만 일치시킵니다. "앞뒤에 무엇이 있는지 알고 있지만 그 사이에 모든 것을 알려주십시오"라고 말하는 패턴으로 "북 엔드"를 만드는 것은 유용한 기술입니다.
양식의 주석과 일치 시키려고한다고 가정하십시오.
-- This is a comment --
당신은 쓸 것 ^--\s+(.+)\s+--$
입니다.
정규 표현식은 재귀 적이므로 이제 이러한 기본 규칙을 이해 했으므로 원하는대로 조합 할 수 있습니다.
† :.
모든 인물과 일치하는 위의 진술 은 엄격하게 사실이 아닌 교육 학적 목적을위한 단순화입니다. 점은 개행을 제외한 모든 문자와 일치 "\n"
하지만 실제로 .+
개행 경계를 넘는 것과 같은 패턴은 거의 기대하지 않습니다 . Perl 정규 표현식에는 예를 들어 모든 문자를 일치 시키기 위해 /s
스위치 와 Java가 있습니다. 이러한 기능이없는 언어의 경우 "공백 또는 비 공백"과 일치 하는 것 , 즉 무엇이든 사용할 수 있습니다.Pattern.DOTALL
.
[\s\S]
a{,m}
적어도 Javascript, Perl 및 Python에서는 문제가되지 않습니다.