티스토리 뷰
정규표현식을 이용해서 가장 많이 접하는 예가 아이디와 패스워드가 제약 조건을 검사하는 것입니다. 여기서는 여러 가지 제약조건을 검사하는 정규표현식의 예를 살펴보겠습니다.
우리는 입력에 대해 검사해야 할 조건이 여러개라면 굳이 하나의 정규표현식 안에 모든 조건을 다 넣어야 하는 것은 아닙니다. 입력 문장을 몇 가지 정규표현식에 대해 차례로 검사하는 것으로 충분합니다. 그를 위해서는 앞에서 살펴본 RegexTestHarnessEjlee 프로그램의 (2)번 메뉴를 이용하면 됩니다. 입력을 먼저 넣고 여러 가지 정규표현식으로 그 입력을 검사해 볼 수 있습니다.
먼저 길이를 검사하는 조건을 생각해 봅시다. 아이디가 6글자 이상이어야 한다 라는 조건을 나타낼 수 있겠지요? 보통 아이디는 영문자와 숫자를 섞어서 쓸 수 있고 단어를 구성하는 문자가 다 가능하므로 \w를 사용하면 됩니다.
(1) regex 먼저 (2) input 먼저 (3) 그룹찾기 (기타) 종료.. 1
regex: \w{6,}
input: 1234567
찾은 문자열 "1234567" (0, 7)
input: abc123
찾은 문자열 "abc123" (0, 6)
input: abc_12
찾은 문자열 "abc_12" (0, 6)
input: abcd
No match found.
input:
영문자, 숫자와 밑줄을 6개 이상 가진 입력을 매치하는 정규표현식입니다. 6글자 미만의 입력에 대해서는 매치되지 않는다는 것을 알 수 있습니다. 문자를 좀더 제약하려면 구체적으로 영문자는 [a-zA-Z], 숫자는 [0-9], 기타 허용하고 싶은 문자는 [-_@] 등으로 쓸 수 있습니다. 문자 집합을 표시한 후 {6,}로 6글자 이상을 나타낼 수 있겠지요?
한 가지 더 수정할 것은 입력이 아이디라면 입력 전체가 패턴에 매치되어야 합니다. 매치된느 부분을 가지고 있는 것으로 충분하지 않겠지요? 이런 경우 ^ ... $로 패턴을 둘러싸면 입력 전체가 매치되어야 함을 보여줍니다.
(1) regex 먼저 (2) input 먼저 (3) 그룹찾기 (기타) 종료.. 1
regex: ^[a-zA-Z0-9]{6,}$
input: abc1234
찾은 문자열 "abc1234" (0, 7)
input: aaa
No match found.
input: **abcd1234**
No match found.
input:
다음은 영문자로 시작해야 한다는 조건을 생각해 봅시다. 시작은 영문자여야 되고 뒤에 나오는 것은 위와 같이 영문자거나 숫자여야 된다는 조건입니다. 그것을 바꿔서 말해보면 첫글자는 영문자여야 되고 뒤에는 위와 똑같은데 길이가 5 이상으로 바뀌어야 되겠지요? 이것을 나타내는 패턴은 다음과 같이 쓸 수 있습니다.
(1) regex 먼저 (2) input 먼저 (3) 그룹찾기 (기타) 종료.. 1
regex: ^[a-zA-Z][a-zA-Z0-9]{5,}$
input: 123456
No match found.
input: abc123
찾은 문자열 "abc123" (0, 6)
input: K1234567A
찾은 문자열 "K1234567A" (0, 8)
input:
모든 영문자를 나타내는 것이 [a-zA-Z]로 써야 되는 것이 좀 불편하지만 어쨌거나 위의 정규식은 우리가 원하는 것을 표현해 줍니다. 숫자는 \d로 가능합니다. 다음으로 영문자와 숫자가 아무거나 나와도 좋은데 반드시 영문자 한 개 이상, 숫자 한 개 이상이 포함되어야 한다는 조건을 생각해 봅시다. 이것은 영문자만, 또는 숫자만으로 된 아이디는 안된다는 조건을 표현하고 싶습니다. 금지 조건을 정규표현식으로 나타내기가 쉽지 않습니다. 안되는 것을 정규표현식으로 표시하고 그것말고 나머지 다 이런 식으로는 표현할 수 없습니다. 프로그램에서 한번더 처리해 준다면 되겠지만 정규표현식만으로는 안된다는 것이지요. 그럼 위의 조건을 다시 한번 생각해 봅시다. 먼저 영문자로 시작하고 숫자 한번 이상을 표현하는 방법을 다음과 같이 생각해 볼 수 있습니다.
regex: ^[a-zA-Z]+\d+[a-zA-Z\d]+$
input: abcdefg
No match found.
input: 12345678
No match found.
input: abcd123ddd
찾은 문자열 "abcd123ddd" (0, 10)
input: 123d456
No match found.
input:
그러면 위의 것과 숫자로 시작하면서 영문자가 한번 이상은 꼭 나온다는 조건을 OR로 표현하면 가능할 것입니다.
regex: ^([a-zA-Z]+\d+[a-zA-Z\d]+|\d+[a-zA-Z]+[a-zA-Z\d]*)$
input: 123d456
찾은 문자열 "123d456" (0, 7)
input: abc333d
찾은 문자열 "abc333d" (0, 7)
input: abcde
No match found.
input: abcdfgh
No match found.
input: 1234567
No match found.
input: a000000
찾은 문자열 "a000000" (0, 7)
input: 000000a000
찾은 문자열 "000000a000" (0, 10)
input:
상당히 복잡한 패턴이 나왔네요. 앞에서 얘기했듯이 안 되는 조건을 나타내려면 그것 빼고 전부를 나타내는 패턴을 구해야 하므로 생각보다 복잡해 집니다. 여기서 |를 이용해서 두 패턴의 합집합을 나타냈습니다. 여기서 주의할 점은 패턴을 나타내는 문자열 안에서는 빈칸이 곧 문자로 인식되므로 빈칸을 넣으면 안 된다는 점입니다. 그 때문에 패턴이 복잡해 지면 가독성이 많이 떨어집니다.
만약 패스워드에 영문자나 숫자가 나오고 특수문자가 하나 이상 나와야 한다는 조건을 표현하려면 어떻게 해야 할까요? 이 경우 [^a-zA-Z0-9]라고 써서 그 이외의 모든 문자를 나타내거나 또는 특수문자는 \W(단어를 구성하는 글자 이외의 문자, 즉 \w가 아닌 것)를 쓰면 어떻게 될까요? 그러면 자판으로 표현할 수 없는 유니코드나 공백까지도 포함되므로 우리가 원하는 조건을 나타내기가 쉽지 않습니다. 제일 확실한 방법은 허용되는 특수 문자를 모두 문자집합으로 나열하는 것입니다. 그렇다고 [~!@#$%^&*(){}[]-_+=\|] 이렇게 쓸 수도 없습니다. 여기에는 문자 집합 안에서 특수한 의미로 해석되는 글자들이 포함되기 때문입니다. 문자 집합을 표기할 때 우리는 ^로 제외할 문자들을 나타내고 [ ]로 내부에 집합을 또 넣을 수 있습니다. 그리고 &는 교집합, -는 0-9처럼 구간을 나타냅니다. 이것들을 제외하면 그대로 문자의 의미를 가집니다. 그러므로 위와 같은 심볼들을 표현하고 싶다면 다음 괕은 정규표현식이 가능합니다. 즉 ^&[]-\는 앞에 escape character \를 붙여주고 나머지는 그대로 쓰면 됩니다.
regex: [~!@#$%\^]+
input: ~!@#$%^
찾은 문자열 "~!@#$%^" (0, 7)
input:
(1) regex 먼저 (2) input 먼저 (3) 그룹찾기 (기타) 종료.. 1
regex: [\&*()\[\]{}\-_=+\\|]+
input: &*()_-=+\|[]{}
찾은 문자열 "&*()_-=+\|[]{}" (0, 14)
input:
그러면 !@#$%^&*()-_=+ 중의 하나를 반드시 포함해야 한다는 조건을 어떻게 나타내면 좋을까요? 앞에서 보았듯이 이것은 여러 번 나와도 되므로 좀 복잡하지만 나타낸다면 다음과 같이 쓸 수 있습니다.
^[a-zA-Z\d]*[!@#$%\^\&*()\-_=+][a-zA-Z0-9!@#$%\^\&*()\-_=+]+$
이것은 세 부분으로 이루어진 패턴이빈다. (1) 영문자 숫자가 0번 또는 여러번 나오다가 (2) 반드시 위의 특수문자가 한번은 꼭 나와야 되고 (3) 뒤에는 영문자, 숫자, 특수문자가 한번 이상 나와야 한다는 조건을 나타내고 있습니다.
그런데 문제는 위 패턴이 패스워드의 길이에 대한 제약을 나타낼 수가 없다는 점입니다. 위의 패턴은 최소 길이 2인 입력을 허용하는데, 특수문자가 제일 먼저 나오면 뒤부분이 5글자 이상이 되어야 하고 특수문자 앞에 영문자나 숫자가 여러 개 나왔다면 특수문자에서 끝나도 됩니다. 그러므로 길이 한정자를 붙이기가 어려워집니다.
그래서 앞에서 얘기했듯이 길이 조건을 검사하는 패턴과 반드시 포함되어야 하는 글자의 조건을 검사하는 패턴을 따로 검사하는 것이 더 좋다는 것입니다.
(1) regex 먼저 (2) input 먼저 (3) 그룹찾기 (기타) 종료.. 2
input: a###123
regex: ^[a-zA-Z\d]*[!@#$%\^\&*()\-_=+][a-zA-Z0-9!@#$%\^\&*()\-_=+]+$
찾은 문자열 "a###123" (0, 7)
regex: .{6,}
찾은 문자열 "a###123" (0, 7)
regex: .{8,}
No match found.
regex:
'컴파일러 - regex와 cfg' 카테고리의 다른 글
lex를 이용한 어휘분석기 예제 (1) (1) | 2019.10.27 |
---|---|
lex 설치와 사용법 (0) | 2019.10.27 |
정규표현식 네번째 - 캡처그룹 (0) | 2019.08.03 |
정규표현식 세번째 - 위치 지정 (0) | 2019.08.03 |
[2] 정규표현식 기초 (0) | 2019.07.29 |
- Total
- Today
- Yesterday
- sort key
- TypeError
- ToString
- 콜렉션
- Lazy evaluation
- APPEND
- comparable
- 동적바인딩
- python example
- C++ 클래스
- contentEquals
- max
- Iterator
- 스트링 +
- contains
- indexof
- rust
- format
- CompareTo
- 이터러블
- Camel Style
- follow
- 자바regex
- 스트링
- 패턴
- zip
- typedef
- 이터레이터
- python exercise
- 지연계산
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |