지난 편에서 [0-9]가 숫자 전체를 뜻한다고 배웠죠? 그런데 숫자를 찾을 때마다 매번 [0-9]라고 적으려니 조금 귀찮지 않으세요? 정규식을 만든 사람들도 똑같이 느꼈나 봐요. 그래서 자주 쓰는 문자 묶음에는 짧은 축약 기호를 만들어 뒀어요. 오늘 배울 \d, \w, \s가 바로 그 주인공이에요. 이 세 개는 실무에서 정말 밥 먹듯이 쓰니까, 오늘 확실히 손에 익혀두면 앞으로 패턴 짜는 속도가 확 빨라져요.
06.1 축약 기호가 왜 생겼을까요?
이유는 딱 하나, 편하려고요. 숫자, 영문자, 공백처럼 우리가 자주 걸러내는 글자 묶음이 있잖아요. 이걸 매번 대괄호로 길게 적는 대신 백슬래시(\) 뒤에 글자 하나를 붙여 짧게 부르기로 한 거예요. 대표 삼총사는 이래요. \d는 숫자(digit), \w는 단어 글자(word), \s는 공백류(space)예요. 영어 단어의 첫 글자를 땄으니 외우기도 쉽죠?
재밌는 규칙이 하나 더 있어요. 이 소문자 기호들을 대문자로 바꾸면 "정반대"가 돼요. \D는 "숫자가 아닌 것", \W는 "단어 글자가 아닌 것", \S는 "공백이 아닌 것"이죠. 지난 편의 부정 [^...]과 비슷한 개념인데, 훨씬 짧게 쓸 수 있어요. 이 "소문자는 그것, 대문자는 반대"라는 짝 규칙 하나면 여섯 개를 통째로 외운 셈이에요.
06.2 \d로 숫자만 뽑아볼까요?
글자와 숫자가 뒤엉킨 문자열에서 숫자 덩어리만 뽑아볼게요. \d는 지난 편의 [0-9]와 완전히 같은 뜻이에요. 여기에 "한 개 이상 이어짐"을 뜻하는 +를 붙여 덩어리로 잡을게요.
import re
re.findall(r"\d+", "abc123def45")
# ['123', '45']
글자 부분인 abc와 def는 전부 무시되고, 숫자 덩어리 123과 45만 잡혔어요. [0-9]+라고 적었어도 결과는 똑같았을 거예요. 그런데 \d+가 훨씬 짧고 읽기 쉽죠? 그래서 실무에서는 대부분 \d를 써요. 저도 숫자를 찾을 땐 손이 자동으로 \d로 가요. 타이핑도 덜하고, 다른 사람이 봐도 "아, 숫자구나" 하고 바로 이해하거든요.
06.3 \w는 어디까지 잡나요?
이번엔 \w예요. 이름이 "단어 글자"라서 알파벳만 잡을 것 같지만, 실제로는 조금 더 넓어요. \w는 영문자, 숫자, 그리고 밑줄(_)을 포함해요. 대괄호로 풀어 쓰면 [A-Za-z0-9_]과 같아요. 밑줄이 포함된다는 게 초보에겐 좀 의외라서 콕 짚고 넘어갈게요. 변수 이름이나 파일 이름에 밑줄이 흔히 쓰이니까 이걸 포함시킨 거예요.
re.findall(r"\w+", "hi_there, world! 42")
# ['hi_there', 'world', '42']
결과를 보세요. hi_there가 통째로 한 덩어리로 잡혔죠? 가운데 밑줄이 \w에 포함되니까 끊기지 않고 이어진 거예요. 반면 쉼표(,)와 느낌표(!)는 단어 글자가 아니라서 경계 역할을 하며 빠졌어요. 그래서 world와 42가 각각 따로 잡혔고요. 숫자 42도 \w에 들어간다는 것도 눈여겨보세요. \w는 숫자까지 품는 넓은 그물이에요. "코드에서 식별자(변수·함수 이름) 같은 토큰을 뽑을 때" \w+를 정말 자주 쓰는 이유가 바로 이거예요.
06.4 공백으로 문장을 어떻게 쪼개나요?
세 번째 주자 \s는 공백류를 뜻해요. 그냥 스페이스뿐 아니라 탭(\t)이나 줄바꿈(\n)까지 전부 포함해요. 눈에는 안 보이지만 자리를 차지하는 "빈 공간" 글자들을 한 번에 가리키는 거죠. 이 \s는 문장을 단어로 쪼갤 때 특히 빛나요. 이번엔 찾기 대신 쪼개기 도구인 re.split을 써볼게요.
text = "one two three\tfour"
re.split(r"\s+", text)
# ['one', 'two', 'three', 'four']
대상 문자열을 보면 two와 three 사이에는 스페이스가 여러 개 있고, three와 four 사이에는 탭(\t)이 끼어 있어요. 보통 이렇게 공백이 제멋대로면 쪼개기가 지저분해지는데, \s+가 "이어진 공백 덩어리"를 통째로 하나의 구분선으로 처리해줘서 결과가 아주 깔끔해요. 스페이스가 몇 개든, 탭이 섞였든 상관없이 네 단어로 딱 나뉘었죠? 사용자가 입력한 지저분한 텍스트를 정리할 때 이 \s+ 조합은 정말 단골 손님이에요.
여기서 초보가 자주 하는 실수 하나를 짚어드릴게요. \s는 눈에 보이는 스페이스만 잡는 게 아니에요. 화면상 똑같아 보여도 사실은 탭이거나, 데이터를 다른 곳에서 복사해 오면서 딸려 온 보이지 않는 공백일 때가 많거든요. 그래서 "분명 스페이스 하나로 나눴는데 왜 빈 값이 섞이지?" 하고 당황하는 일이 생겨요. 이럴 때 \s+처럼 +를 붙여 "공백이 몇 개든, 어떤 종류든 한 덩어리로" 처리하면 그런 잔버그가 확 줄어요. 저는 사용자 입력을 다룰 땐 거의 반사적으로 \s 하나가 아니라 \s+를 써요.
06.5 대문자 \D \W \S는 뭐가 다른가요?
앞에서 "대문자는 반대"라고 했죠? 이제 직접 확인해 볼게요. \D는 숫자가 아닌 글자를 뜻해요. \d가 숫자였으니 그 반대인 거죠.
re.findall(r"\D+", "12ab34cd")
# ['ab', 'cd']
이번엔 반대로 숫자 12와 34가 빠지고, 숫자가 아닌 ab와 cd만 잡혔어요. \d였다면 정확히 반대 결과가 나왔겠죠. 이렇게 소문자와 대문자는 서로 정반대의 짝이에요. 같은 원리로 \W는 "단어 글자가 아닌 것"이라 공백이나 문장부호를 잡고, \S는 "공백이 아닌 것"이라 실제 글자만 잡아요. 여섯 개를 따로 외울 필요 없이 "소문자 셋과 그 반대"로 묶어서 기억하면 훨씬 쉬워요.
실무 팁을 하나 드리면, \S는 "공백만 아니면 뭐든"이라 아주 넓은 그물이에요. 그래서 "공백으로 구분된 아무 토큰이나" 잡고 싶을 때 \S+를 즐겨 써요. 예를 들어 로그 한 줄에서 공백으로 나뉜 항목들을 대충 뽑을 때 유용하죠. 반대로 \D는 "숫자만 아니면 뭐든"이라, 숫자 사이에 낀 구분자나 단위를 걸러낼 때 손이 가요. 이렇게 대문자 축약은 "원치 않는 한 종류만 콕 집어 빼고 싶을 때" 아주 편해요.
06.6 축약 기호를 정리하면요?
![[정규식 06] 숫자·문자·공백 축약, \d \w \s](https://img.thenullpage.com/posts/6590/6590_1_30c649.webp)
오늘 배운 걸 표처럼 머릿속에 정리해 볼게요. 여섯 개지만 사실 세 쌍이라 부담이 적어요.
먼저 소문자 삼총사예요. \d는 숫자로 [0-9]와 같고, \w는 단어 글자로 [A-Za-z0-9_]과 같으며 밑줄이 포함된다는 게 포인트였어요. \s는 공백류로 스페이스, 탭, 줄바꿈을 아우르죠. 그리고 대문자는 각각의 반대예요. \D는 숫자 아님, \W는 단어 글자 아님, \S는 공백 아님이고요.
한 가지 더 당부할게요. 이 축약 기호들은 파이썬뿐 아니라 자바스크립트, 자바, 그리고 터미널의 grep 같은 도구에서도 거의 똑같이 통해요. 정규식의 큰 장점이 바로 이 "한 번 배우면 어디서나 쓴다"는 점이에요. 그러니 오늘 익힌 \d, \w, \s는 특정 언어에서만 쓰는 지식이 아니라 평생 써먹는 공용 도구라고 생각하고 확실히 손에 붙여두세요. 짧은 기호 세 쌍이지만, 이것만 자유자재로 다뤄도 웬만한 텍스트 처리는 다 해낼 수 있어요.
이 축약 기호들은 앞으로 나올 거의 모든 실전 패턴에 부품처럼 들어가요. 전화번호에는 \d가, 사용자 이름 검사에는 \w가, 입력 정리에는 \s가 빠지지 않고 등장하죠. 오늘 예제들을 직접 쳐보면서 \d와 [0-9]가 정말 같은 결과를 내는지, \w가 밑줄을 삼키는지 눈으로 확인해보세요. 손끝으로 한 번 겪어두면 이 짧은 기호들이 얼마나 든든한 무기인지 금방 느끼실 거예요.