보안/Blue

정규표현식 정리

melonbbang-ruffy 2024. 10. 23. 17:21

시큐어 코딩에 대해서 공부해 보면서 실무에서는 많이 안쓰일지는 몰라도 매일 보는 표현인데 항상 볼 때마다 헷갈려서(...ㅋㅋㅋ) 이번 기회에 정리해 보고자 한다.

정규표현식

특정 패턴을 가진 문자열을 찾거나 매칭할 때 쓰이는 코드

. (점)

아무 문자 하나를 의미한다.

단일 문자가 무엇이든 매칭하겠다는 의미

import re

pattern = r'a.c'

test = "abc axc a7c ac"

matches = re.findall(pattern, test)
print(matches)

여기서, a.c는 a와 c 사이에 어떤 문자열이 와도 매칭된다. 그러나 .은 무조건 문자 하나가 들어가야 한다는 의미이므로, 만약 문자가 없으면 매칭되지 않는다.

ac는 매칭되지 않았다.

^ (캐럿)

문자열이 어떠한 특정 문자로 시작하는지 확인할 때 사용되는 메타 문자이다

만약 "^python" 이라고 되어 있을 경우, 문자열 python 이라고 시작되는 특정 문자열들만 매칭된다는 의미이다.

import re

pattern = r'^python'

test = "python pythoni pypytorch"
matches = re.findall(pattern, test)
print(matches)

여기서 주의해야 될 점은 ^는 문자열이 python이라는 문자열 패턴으로 시작하는지 확인하겠다는 의미로, 전체 문자열 자체가 "python pythoni pypytorch" 이기 때문에 "python"만 매칭된 걸 확인할 수 있다. 

즉 전체 문자열을 보고 있기 때문에 python 하나만 매칭된다는 의미, 마찬가지로 test의 문자열을 "pythoni pythoni pypytorch" 이런 식으로 주어져도 python을 출력하는 걸 볼 수 있다.

$ (달러)

문자열의 끝을 의미하는 메타문자이다.

만약 "python$" 이라고 되어 있을 경우, 문자열의 끝이 python 이라고 끝나는 특정 문자열들만 매칭이 된다는 의미이다.

import re

pattern = r'python$'

test = "123python python abcpython"

matches = re.findall(pattern, test)
print(matches)

 

마찬가지로 문자열 전체("123python python abcpython") 에서 python으로 끝나는 것만을 확인하고 있고, abcpython이라는 문자열로 끝날 때, 해당 문자열의 끝부분에 python 문자열이 들어가 있는 걸 확인하였으므로 매칭된 것을 볼 수 있다.

 

만약 아래의 코드로 실행할 경우....?

import re

pattern = r'python$'

test = "123python python abc"

matches = re.findall(pattern, test)
print(matches)

전체 문자열 "123python python abc"에서 python을 빼 보았다.

아무것도 출력 안된 것을 확인할 수 있다.

* (별표)

0개 이상의 반복

"a*"라고 표현될 경우, a라는 문자가 없거나 1개 이상 온다는 의미이다.

import re

pattern = r'a*'

test = "bcdaaefg"

matches = re.findall(pattern, test)
print(matches)
# 결과 : ['', '', '', 'aa', '', '', '', '']

 

? (물음표)

0개 또는 1개만 반복된다는 의미

과한 사용 저지(시큐어 코딩)를 위해 뒤에 붙어서 사용되기도 한다.

예를 들어, "a?"라고 표현될 경우, a라는 문자가 아예 없거나 1개만 온다는 의미이다.

import re

pattern = r'a?'

test = "bcdaaefg"

matches = re.findall(pattern, test)
print(matches)

이렇게 아예 공백(안오는 경우)이 오거나, a 문자 하나만 매칭되는 걸 볼 수 있다.

 

+ (플러스)

1개 이상의 문자의 반복을 의미하는 메타 문자이다.

'a+'로 되어 있을 경우, a라는 문자가 a를 포함해서 1개 이상 와야한다는 의미이다.

# b라는 문자가 1개 이상 오는 문자열들을 찾고 싶을 때
import re

pattern = r'ab+'
test = "a ab abb abbb"
matches = re.findall(pattern, test)
print(matches)

 

[] 대괄호

대괄호 안에 나열된 문자 중 하나라도 오는 문자열을 찾는다는 의미

[aeiou] 가 있다고 가정하면, 여기서 a, e, i, o, u 중 한개의 문자라도 들어있는 문자열들을 찾는다는 의미이다.

import re

pattern = r'[aeiou]'
test_string = "hello world"
matches = re.findall(pattern, test_string)
print(matches)

+) 헷갈려서 다시 정리

[a, e, i, o, u] 이렇게 있을 경우, 대괄호 안에 들어있는 문자들 중 하나의 문자가 테스트하고자 하는 문자열에 들어있다면 매칭하는 메타문자이다.

예를 들어, aeir라는 문자열이 있다고 가정하자, pattern = [a, e, i, o, u] 이렇게 두고, test string으로 aeir를 두면 매칭된 결과값으로 'a', 'e' , 'i'가 나온다.

import re

pattern = r'[aeiou]'
test_string = "aeir"
matches = re.findall(pattern, test_string)
print(matches)

대괄호 안에 있는 여러 문자들을 동시에 매칭하는 게 아니라, 오로지 하나의 문자만 매칭해서 찾아주는 메타문자이다.

[abc] => a, b, c 중에서 오로지 1개의 문자만 매칭하겠다.

([abc]) => 그 결과로, 1개의 매칭된 문자열만 들어온다.

 

() 괄호

특정 패턴들을 하나의 그룹으로 묶어 그룹화하는 메타문자

이렇게 묶여진 특정 패턴의 그룹이 들어있는 문자열을 찾는다는 의미이다.

만약 (abc) 이렇게 묶여져 있을 경우, abc가 오는 문자열을 찾는다는 의미이다.

추가적으로, "(abc)+" 이렇게 표시할 경우, +는 최소한 1개 이상의 문자가 와야 한다는 의미이므로, abc가 1번 이상 반복되는 문자열을 찾겠다는 의미이다.

import re

pattern = r'(abc)+'

test = "ab abc abc"
matches = re.findall(pattern, test)
print(matches)

 

\ (역슬래시)

이스케이프 문자

메타문자를 문자 그대로 찾고 싶을때, 메타 문자 앞에 쓴다.

예를 들어 문자열에서 $를 찾고 싶을 때, \$를 써서 문자열에서 $를 확인한다.

import re

pattern = r'\$'

test = "The price is $100"

matches = re.findall(pattern, test)

print(matches)

{} (중괄호)

반복을 나타낸다.

 

  • {n}: 정확히 n번 반복
  • {n,}: 최소 n번 이상 반복
  • {n,m}: 최소 n번, 최대 m번 반복

만약 어떤 문자로 시작하는 문자열을 찾고 싶다면, {a, } (a로 시작하는 문자열을 찾겠다.) 이렇게 작성해도 된다. 

예를 들어, 'a{2, 4}' 이렇게 작성했다고 가정하자.

그러면 a는 최소 앞의 a를 포함해서 2문자 이상, 4문자 이하가 와야한다는 의미이다.

import re

pattern = r'a{2,4}'
test = "a aa aaa aaaa aaaaa"
matches = re.findall(pattern, test)
print(matches)

 

'aaaaa'는 'aaaa' 까지만 찾은 걸 볼 수 있다. 4문자 이상은 찾지 않는다는 것....