직전 게시물 마지막 예제 문제를 해결하면서 문자열을 처리하는 메소드가 잠깐 등장했었다.
오늘날에는 아주 다양한 데이터들이 있지만,
사람이 읽을 수 있는 텍스트 형태의 데이터를 다룰 줄 아는 것은 아주 중요하다.
이번 장에서는 텍스트를 처리하는 연산들과 메소드들을 알아보도록 하자.
텍스트 데이터는 구조화된 데이터(HTML, XML, CSV, JSON 등)와
구조화되지 않은 문서(자연어로 된 텍스트)로 나눌 수 있다.
일반적으로 데이터는 가공된 형태가 아니기 때문에 우리는 이 데이터를 수정해서 완전한 데이터로 만들어야 한다.
예를 들어 텍스트 데이터에 대소문자가 섞여 있을 수도 있고,
문자열의 앞뒤에 필요없는 공백 문자가 붙어 있을 수도 있다.
또 긴 문자열 중에서 우리가 필요한 것은 일부분일 수도 있다.
이러한 여러 가지 경우에서 문자열을 다룰 줄 아는 능력은 꼭 필요하다.
문자열에서 가장 기본적인 작업은, 문자열 안에 있는 개별 문자들을 추출해내는 작업일 것이다.
하지만 우리는 이미 이것을 할 줄 안다.
기억이 나지 않는다면, 아래 게시글을 참고해보자.
"이건 리스트지 문자열이 아니지 않나요?"
맞다. 하지만 우리는 리스트를 슬라이싱 하는 법을 배웠다.
문자열은 리스트와 마찬가지로 인덱스를 이용해서 접근할 수 있고,
슬라이싱을 이용해 원하는 문자를 추출할 수도 있다.
다음과 같이 'Hello Python' 이라는 문자열이 변수 s 에 저장되어 있다고 하자.
s = 'Hello Python'
print(s[0]) # 'H'
위의 예제에서는 인덱스 0을 이용하여 첫번째 문자인 'H' 를 뽑아내는 것을 확인할 수 있다.
그렇다면 s[-1] 은 어떻게 될까?
리스트에서 인덱싱을 공부했다면 예상할 수 있듯이,
문자열의 마지막 문자를 반환한다.
s = 'Hello Python'
print(s[-1]) # 'n'
그렇다면 이번에는 슬라이싱을 진행해보자.
리스트에서 한 것과 마찬가지로 콜론을 이용해 인덱스를 설정하면 특정 문자열을 뽑아낼 수 있다.
위 문자열에서 'Python' 이라는 문자열을 뽑아내고 싶다면 어떻게 하면 될까?
s = 'Hello Python'
print(s[6:]) # 'Python'
위와 같이 슬라이싱 하면 된다.
그렇다면 이번엔 메소드들을 이용해 문자열을 잘라보고, 이어붙여보자.
문자열을 자르는 것은 split() 메소드를 이용하면 된다.
split() 메소드는 구분자를 이용해 문자열을 토큰들의 리스트로 반환하며,
별도의 구분자를 지정하지 않을 경우 공백 단위로 분리한다.
예들 들어 다음과 같은 s 문자열에 split() 메소드를 사용하면 공백을 구분자로 사용하여
하나의 문자열을 3개의 문자열로 분리할 수 있다.
s = 'Welcome to Python'
print(s.split())
# ['Welcome', 'to', 'Python']
split() 메소드의 인자로 구분자를 설정해줄 경우엔 해당 구분자 단위로 문자열을 구분할 수 있다.
아래는 마침표로 구분해서 문자열을 뽑아낸 것이다.
s = '2021.06.18'
print(s.split('.'))
# ['2021', '06', '18']
이번에는 문자열을 자르는 것이 아니라 이어붙여보자.
문자열을 이어붙이는 것 역시 메소드를 사용해서 간편하게 할 수 있다.
이어붙이는 메소드는 join() 을 사용하면 된다.
s = ','.join(['apple', 'grape', 'banana'])
print(s)
# apple,grape,banana
위의 예제를 보면 join() 은 접착제 역할을 하는 문자를 문자열 사이에 넣는다.
위 코드에서는 쉼표를 접착제 역할을 하는 문자로 설정하였다.
세 개의 문자열을 쉼표를 중간중간 삽입하여 하나의 문자열로 합치는 것을 볼 수 있다.
list() 함수를 이용하면 문자열을 문자 하나씩 구분하여 리스트로 만들 수 있는데
join() 함수를 이용하면 다시 원래의 문자열로 만들 수 있다.
문자열 안에 있는 문자를 특정 문자로 바꾸고 싶을 때는 replace() 메소드를 사용한다.
s = '010.1234.5678'
s = s.replace('.', '-')
print(s)
# 010-1234-5678
replace() 메소드의 첫 번째 인자로는 대상이 되는 문자를, 두 번째 인자로는 바꾸고 싶은 문자를 넣어주면 된다.
문자열에서 대문자를 소문자로 변경하는 함수도 있다.
이는 lower() 함수이고, 반대로 소문자를 대문자로 변경하는 메소드는 upper() 함수이다.
s = 'Hello, World'
print(s.lower()) # hello, world
print(s.upper()) # HELLO, WORLD
문자열에서 원치 않는 공백을 제거할 때는 strip() 함수를 이용하면 된다.
strip() 메소드는 문자열의 첫 부분과 끝 부분에서 공백 문자를 제거한다.
s = ' Hello, World '
print(s.strip()) # Hello, World
find() 메소드는 문자열에서 지정된 부분 문자열을 찾아서 그 인덱스를 반환한다.
지정된 문자를 찾지 못 했을 경우에는 -1 을 반환한다.
s = 'This is Example'
print(s.find('Ex')) # 8
문자열에서 count() 메소드는 문자열 중에서 부분 문자열이 등장하는 횟수를 반환한다.
s = 'twix.tistory.com'
print(s.count('.')) # 2
이제 1회용 비밀번호를 만드는 예제를 통해서 좀 더 알아보자.
파이썬의 random() 함수는 난수를 만들어주는 함수인데, 이를 사용하여 비밀번호를 만들어보자.
몇 자리의 비밀번호를 원하는지 물어본 뒤에 입력된 자릿수를 가진 비밀번호를 생성해보자.
먼저 고민해보고 코드를 짜보자.
이제 해답 코드를 살펴보겠다.
import random
n_digits = int(input('몇 자리의 비밀번호를 원하십니까? '))
otp = ''
for i in range(n_digits) :
otp += str(random.randrange(0, 10))
print(otp)
random 모듈의 randrange(0, 10) 을 사용하면 0에서 9까지의 임의의 정수값을 얻을 수 있다.
이 정수를 str() 함수를 이용하면 문자열로 바꿀 수 있다.
그리고 매번 생성된 숫자를 더하기 연산으로 결합하는 방식으로
사용자의 원하는 개수의 숫자를 하나의 문자열로 담을 수 있다.
이번에는 정규식에 대해서 알아보자.
정규식이란 특정한 규칙을 가지고 있는 문자열들을 표현하는데 사용되는 규칙을 가진 언어이다.
파이썬에서 정규식을 사용하려면 re 모듈을 포함시켜야 한다.
모듈을 포함시키기 위해서는 import 문을 이용한다.
import re
txt = 'Life is too short, you need python'
print(re.search('Life', txt))
# re.Match object; span=(0, 4), match='Life'>
re 모듈의 search() 메소드를 사용하면 매치되는 문자열을 찾을 수 있다.
이때 찾을 문자열을 정규 표현식으로 나타낼 수 있는데,
정규식을 익히는 데는 노력이 필요하다.
여러 메타 문자들이 있는데 주요 메타문자들을 살펴보면 다음과 같다.
식 | 기능 | 설명 |
^ | 시작 | 문자열의 시작을 의미함 |
$ | 끝 | 문자열의 끝을 의미함 |
. | 문자 | 한 개의 문자 |
[abc] | 문자 선택 범위 | a, b, c 가운데 하나의 문자 |
[^abc] | 문자 제외 범위 | a, b, c 가 아닌 어떤 문자 |
| | 또는 | | 앞의 문자 또는 뒤의 문자를 의미함 |
이제 다시 예제를 살펴보며 정규식에 익숙해져보자.
패스워드 검사 프로그램을 만들텐데, 사용자가 패스워드를 입력하도록 하고
이 패스워드가 조건에 맞지 않을 경우 다시 입력하도록 while 문을 사용하자.
패스워드의 조건은 다음과 같고, re 모듈을 import 하여 정규식을 이용해보자.
1. 최소 8글자
2. 적어도 하나의 영문자 대문자 및 소문자를 포함
3. 적어도 하나의 숫자 포함
4. 다음에 나타난 특수문자[_, @, $, !] 중 하나를 포함
원하는 결과 화면은 다음과 같다.
해답 코드를 살펴보자.
import re
while True:
password = input("패스워드를 입력하세요 : ");
if len(password)<8 or not re.search("[a-z]", password) or \
not re.search("[A-Z]", password) or \
not re.search("[0-9]", password) or not re.search("[_@$!]", password):
print("유효하지 않은 패스워드!")
else:
print("유효한 패스워드")
break
네 가지 조건을 바탕으로 정규식을 이용한 검색을 하여 검색이 되는지를 확인하면 된다.
우선 len(password) 를 이용하여 문자열의 길이가 8보다 큰지 검사한다.
다음으로 search('[a-z]') 를 통해서 영문자 소문자를 포함하고 있는지를 검사한다.
또 search('[A-Z]') 를 통해서 영문자 소문자를 포함하고 있는지 검사한다.
이러한 방식으로 각각의 조건을 하나씩 검사하면 된다.
이번 장에서는 문자열을 다루는 방법에 대해 공부해보았다.
파이썬은 다양한 메소드를 제공하기 때문에 문자열을 다루기 간편하다.
물론 메소드나 정규표현식이 익숙치 않아 어려울 수 있지만,
데이터과학을 파이썬을 이용해 다룰 때에 이러한 내용들은 필수이기 때문에 꼭 필요하다.
이제 다음 장에서는 넘파이를 이용해 수치 데이터를 처리해보고 데이터과학의 세계로 나아가보자.
출처 : 따라하며 배우는 파이썬과 데이터 과학 - 천인국, 박동규, 강영민