티스토리 뷰

정규표현식을 이용해서 가장 많이 접하는 예가 아이디와 패스워드가 제약 조건을 검사하는 것입니다. 여기서는 여러 가지 제약조건을 검사하는 정규표현식의 예를 살펴보겠습니다. 

우리는 입력에 대해 검사해야 할 조건이 여러개라면 굳이 하나의 정규표현식 안에 모든 조건을 다 넣어야 하는 것은 아닙니다. 입력 문장을 몇 가지 정규표현식에 대해 차례로 검사하는 것으로 충분합니다. 그를 위해서는 앞에서 살펴본 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: 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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 31
글 보관함