정규 표현식을 잘 이해하지 못합니다. 이해하기 쉽게 설명해 주실 수 있나요? 온라인 도구나 책이 있다면 링크도 제공해 주실 수 있나요?
가장 중요한 부분은 개념입니다. 구성 요소의 작동 방식을 이해하고 나면 구문의 차이는 가벼운 방언에 불과합니다. 정규식 엔진의 구문 위에 있는 계층은 사용 중인 프로그래밍 언어의 구문입니다. Perl과 같은 언어는 이러한 복잡성을 대부분 제거하지만 C 프로그램에서 정규 표현식을 사용하는 경우 다른 고려 사항을 염두에 두어야 합니다. 정규 표현식을 원하는 대로 조합할 수 있는 빌딩 블록으로 생각하면 자신만의 패턴을 작성하고 디버깅하는 방법뿐만 아니라 다른 사람이 작성한 패턴을 이해하는 방법을 배우는 데 도움이 됩니다.
개념적으로 가장 간단한 정규식은 리터럴 문자입니다. 패턴 N
은 문자 'N' 과 일치합니다.
서로 옆에 있는 정규식은 시퀀스와 일치합니다. 예를 들어, Nick
패턴은 'N', 'i', 'c', 'k' 시퀀스와 일치합니다.
유닉스에서 grep
을 사용해 본 적이 있다면, 심지어 평범해 보이는 문자열을 검색하기 위해서라도, 이미 정규식을 사용하고 있는 것입니다! (grep
의 re
는 정규 표현식을 나타냅니다.)
조금만 더 복잡하게 만들면 '닉'이나 '닉'을 패턴 '[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-9]+
(및 이에 상응하는 \d+
)는 음수가 아닌 모든 정수와 일치합니다.\d{4}-\d{2}-\d{2}
는 2019-01-01과 같은 형식의 날짜와 일치합니다.수량화자는 패턴을 바로 왼쪽으로 수정합니다. 0abc+0이 '0abc0', '0abcabc0' 등과 일치할 것으로 예상할 수 있지만, 더하기 수량화자의 왼쪽에 있는 패턴은
c입니다. 즉,
0abc+0은 '0abc0', '0abcc0', '0abccc0' 등과 일치합니다. 끝에 0이 있는 하나 이상의 'abc' 시퀀스를 일치시키려면
0(abc)+0을 사용합니다. 괄호는 단위로 정량화할 수 있는 하위 패턴을 나타냅니다. 또한 정규식 엔진은 입력 텍스트에서 괄호로 묶인 그룹과 일치하는 부분을 저장하거나 '캡처'하는 것이 일반적입니다. 이러한 방식으로 비트를 추출하는 것이 인덱스와
substr`을 계산하는 것보다 훨씬 더 유연하고 오류가 적습니다.
앞에서 '닉'이나 '닉'을 일치시키는 한 가지 방법을 살펴봤습니다. 다른 하나는 Nick|nick
에서와 같이 대체를 사용하는 것입니다. 대체에는 왼쪽의 모든 것과 오른쪽의 모든 것이 포함된다는 것을 기억하세요. 그룹 괄호를 사용하여 |
의 범위를 제한합니다(예: *, (Nick|nick)
).
다른 예로, [a-c]
를 a|b|c
로 동일하게 작성할 수도 있지만, 많은 구현에서 대체 길이가 1보다 크다고 가정하기 때문에 이는 차선책일 가능성이 높습니다.
일부 문자는 자체적으로 일치하지만 다른 문자는 특별한 의미를 갖습니다. '\d+패턴은 백슬래시 뒤에 소문자 D와 더하기 기호가 뒤따르는 패턴과 일치하지 않으므로 이를 얻기 위해 '\\d\+
를 사용해야 합니다. 백슬래시는 다음 문자에서 특별한 의미를 제거합니다.
정규식 수량화자는 욕심이 많습니다. 즉, 전체 패턴이 성공적으로 일치하도록 허용하면서 가능한 한 많은 텍스트를 일치시킵니다.
예를 들어 입력이 다음과 같다고 가정해 보겠습니다.
"안녕하세요." 그녀가 "잘 지내세요?"라고 말했습니다;
'.+'가 '안녕하세요'와만 일치할 것으로 예상했다가 '안녕하세요'에서 '당신'까지 모두 일치하는 것을 보고 놀랄 수도 있습니다.
욕심을 부리는 것에서 조심스럽게 생각하는 것으로 바꾸려면 수량자에 ?"
를 추가하면 됩니다. 이제 질문의 예제인 \((.+?)\)
가 어떻게 작동하는지 이해하셨을 것입니다. 이는 리터럴 왼쪽 괄호로 시작하여 하나 이상의 문자가 오고 오른쪽 괄호로 끝나는 시퀀스와 일치합니다.
입력이 '(123) (456)' 인 경우 첫 번째 캡처는 '123' 이 됩니다. 욕심이 없는 정량화자는 나머지 패턴이 가능한 한 빨리 매칭을 시작할 수 있도록 하길 원합니다.
((.+?))`가 같은 역할을 하는 정규 표현식 방언이 있는지 모르겠습니다. 전송 중 어딘가에서 무언가가 손실된 것 같습니다).
입력의 시작 부분에만 일치하려면 특수 패턴 ^
를 사용하고 끝 부분에만 일치하려면 $
를 사용합니다. "앞뒤에 무엇이 있는지 알지만 그 사이는 모두 알려주세요."라고 말하는 패턴으로 '북엔드'를 만드는 것은 유용한 기법입니다.
다음과 같은 형식의 주석을 일치시키고 싶다고 가정해 보세요.
"-- 이것은 코멘트입니다 --
'^--\s+(.+)\s+--$
를 작성하면 됩니다.
정규식은 재귀적이므로 이제 이러한 기본 규칙을 이해했으니 원하는 대로 조합할 수 있습니다.
RegExr(JavaScript용)
Perl: YAPE: 정규식 설명
RegexPal]4 (자바스크립트용)
정규 표현식 온라인 테스터]5
Regex 101 (PCRE, 자바스크립트, 파이썬, 골랑용)
Expresso (.NET용)
루뷸러]10 (루비용)
정규식 라이브러리]11 (일반적인 시나리오를 위한 사전 정의 정규식)
정규식 테스터 (자바스크립트용)
정규식 스톰 (.NET용)
디버그엑스]15 (시각적 정규식 테스터 및 도우미)
정규식 치트 시트]19
정규식 쿡북]20
정규 표현식 - 알아야 할 모든 것]23 (PDF 시리즈)
정규식 구문 요약]24[24
†: .
는 모든 문자와 일치한다는 위의 문장은 교육적 목적을 위해 단순화한 것으로 엄밀히 말하면 사실이 아닙니다. 점은 개행인 "\n"
을 제외한 모든 문자와 일치하지만 실제로는 .+
와 같은 패턴이 개행 경계를 넘을 경우는 거의 없습니다. 예를 들어 Perl 정규식에는 .
가 어떤 문자와도 일치하도록 하는 /s
스위치 및 Java Pattern.DOTALL
가 있습니다. 이러한 기능이 없는 언어의 경우 [\s\S]
와 같은 것을 사용하여 모든 공백 또는 공백이 아닌 모든 공백
, 즉 무엇이든 일치시킬 수 있습니다.