Regular Expression
정규 표현식 또는 정규식은 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다. 정규 표현식은 많은 텍스트 편집기와 프로그래밍 언어에서 문자열의 검색과 치환을 위해 지원하고 있으며, 특히 펄과 Tcl은 언어 자체에 강력한 정규 표현식을 구현하고 있다.
Meta word
정규표현식에서 일정한 의미를 가지고 쓰는 특수문자를 메타 문자라고 부른다. 여기에 쓰이는 글자가 포함된 패턴을 넣으려면 해당 글자 앞에 \를 넣어줘야 한다.
- ^ : 문자열의 시작
- $ : 문자열의 종료. 옵션에 따라 문장의 끝 또는 문서의 끝에 매치된다.
- . : 임의의 한 문자
- []: 문자 클래스. 문자 클래스 안에 들어가 있는 문자는 그 바깥에서 하나의 문자로 취급된다.
- ^ : 문자 클래스 내에서 ^는 not
-
- : ex) a-z는 a에서 z까지의 문자
-
: or를 나타냄 - ? : 앞 문자가 없거나 하나 있음
-
- : 앞 문자가 하나 이상임
-
- : 앞 문자가 0개 이상임
- {n,m} : 앞 패턴이 n개 이상 m개 이하. {0,1} 은 ?와 같은 의미다.
- {n,} : 앞 패턴이 n개 이상. 위의 형태에서 m이 생략된 형태이다. {0,} 이면 *와 같고 {1,} 이면 +와 같은 의미이다.
- {n} : 앞 패턴이 정확히 n개. {n,n} 과 같은 의미이다.
- () : 패턴 그룹. 하나의 패턴구분자 안에 서브 패턴을 지정해서 사용할 경우 괄호로 묶어주는 방식을 사용한다.
- \s : 공백문자. 대문자로(\S) 적으면 반대를 의미한다.
- \b : 문자와 공백 사이를 의미한다. 공백, 탭, 컴마, 대시 등이 올 수 있다. 대문자로(\B) 적으면 반대를 의미한다. (ex) \bplay\b일때 playground(x) let’s play around(o) )
- \d : 숫자 [0-9]와 같다. 대문자로(\D) 적으면 반대를 의미한다.
- \t : 탭문자
- \w : 단어 영문자+숫자+(밑줄) [0-9a-zA-Z] 대문자로(\W) 적으면 반대를 의미한다.
패턴 변경자
패턴구분자가 끝나면 그 뒤에 쓰는 것으로, 패턴에 일괄적으로 변경을 가할 때 사용한다. 정규식 엔진에 따라 변경자의 적용 방식이 상이하므로 해당 구현의 매뉴얼을 읽어야 한다.
예를 들어 대소문자 무시 플래그의 경우 자바스크립트는 /패턴/i 로 쓰지만 파이썬에서는 re.compile(패턴, flags=re.I) 로 Go에서는 (?i)패턴으로 쓴다.
- i : 패턴을 대소문자 구분 없이 검사한다. 이 변경자를 사용할 경우 [a-z]로만 검사해도 자동으로 [a-zA-Z]와 같은 기능을 하게 된다. 영어가 아닌 언어(독일어, 프랑스어 등)를 다룰 때에는 버그 가능성이 있으므로 쓰지 않는 게 좋다. 대소문자라는 개념이 없는 한글, 한자, 가나문자는 이 패턴 변경자가 아무 역할도 하지 않는다.
- s : 임의의 한 문자를 가리키는 . 메타 문자에 개행 문자(\n)도 포함시키도록 한다. 이 변경자를 사용하면 .이 줄바꿈도 임의의 한 문자로 취급하여 찾는다.
- g : ^문자가 문장이 아닌 문서의 처음에, $ 문자가 문장의 끝(라인 피드 \n)이 아닌 주어진 문자열의 끝에 매치되게 변경한다.
- m : 주어진 문자열에 줄바꿈이 있을 경우, 여러 줄로 취급하여 검사한다. (줄바꿈이 없다면 써도 의미가 없다.) 원래 정규표현식을 쓸 때 줄바꿈은 무시되는데, 이걸 사용하면 줄바꿈을 적용해서 검사한다. 그리고 ^은 한 줄의 시작, $는 한 줄의 끝으로 의미가 달라진다.
- x : 공백 문자를 무시한다. 단, 이스케이프(역슬래쉬하고 같이 쓸 경우)하거나 문자 클래스 안에 있을 경우에는 예외. 정규식을 조금 더 읽기 편하게 만들어준다. 그러나 이 변경자를 지원하지 않는 엔진이 많은 게 단점이다.
탐욕적 및 게으른 수량자
정규표현식에서는 일치하는 패턴을 찾는 횟수제한이 없어 필요이상의 상황을 연출하기도 하는데 이것은 의도적으로 수량자를 탐욕적으로 만들었기 때문이다.
문법에서 말하는 탐욕적 수량자란 가능하면 가장 큰 덩어리를 찾는다는 뜻이며, 반대의 개념인 게으른 수량자(Lazy Quantifier)는 패턴에 근접하는 최소한의 덩어리를 찾는다.
사용 예(Python)
>>> data = "<div> <p>First</p> <p>Second</p></div>"
>>> import re
>>> re.findall(r"<p>(.+)</p>", data) # 기본적으로 탐욕적인 매칭
['First</p> <p>Second']
>>> re.findall(r"<p>(.+?)</p>", data) # 게으른 수량자 사용
['First', 'Second']
IP Regex
IPv4
/^(([0-9] | [1-9][0-9] | 1[0-9]{2} | 2[0-4][0-9] | 25[0-5]).){3}([0-9] | [1-9][0-9] | 1[0-9]{2} | 2[0-4][0-9] | 25[0-5])$/ |
reference
https://regexone.com/
https://regexr.com/
explain
https://namu.wiki/w/%EC%A0%95%EA%B7%9C%20%ED%91%9C%ED%98%84%EC%8B%9D?from=%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D
https://soooprmx.com/archives/7718
Java Patterns and Matchers methods
java에선 주로 patterns와 matchers클래스로 정규표현식을 다룬다. String.replaceAll(regex, replace)같은 예외도 존재한다.
Matcher 클래스 메서드들
find() : 패턴이 일치하는 경우 true를 반환하고, 그 위치로 이동(여러개가 매칭되는 경우 반복 실행가능) find(int start) : start위치 이후부터 매칭검색을 수행 start() : 매칭되는 문자열 시작위치 반환 start(int group) : 지정된 그룹이 매칭되는 시작위치 반환 end() : 매칭되는 문자열 끝 다음 문자위치 반환 end(int group) : 지정되 그룹이 매칭되는 끝 다음 문자위치 반환
group() : 매칭된 부분을 반환 group(int group) : 매칭된 부분중 group번 그룹핑 매칭부분 반환 groupCount() : 패턴내 그룹핑한(괄호지정) 전체 갯수 반환 matches() : 패턴이 전체 문자열과 일치할 경우 true 반환
Group
패턴 내에서 그룹을 지정하기 위해서 ()를 통해 그룹을 설정해주면 되고, () 갯수만큼 그룹이 만들어 진다.
위 예제에서는 2개의 그룹이 설정이 되었으며, 각 그룹은 group()메서드를 통해 1,2번으로 접근이 가능하다.
group()나 group(0) 메서드는 매칭된 전체 문자열을 반환한다.
matching index
start()메서드를 통해 패턴이 일치하는 문자열의 시작 위치와 end() 메서드를 통해 패턴이 끝나는 문자열의 다음 문자위치를 반환한다.
end() 메서드가 패턴이 일치하는 문자열의 끝부분 위치가 아닌 끝부분 다음 문자의 위치이다.
start(int group)와 end(int group)에 group이 지정되는 경우 해당 그룹이 매칭되는 위치를 반환하게 된다.
https://enterkey.tistory.com/353