텍스트 처리 기본 (Text Processing Fundamentals)

Intermediate

This tutorial is from open-source community. Access the source code

소개

이 섹션에서는 텍스트 작업 방법을 소개합니다.

이것은 가이드 실험입니다. 학습과 실습을 돕기 위한 단계별 지침을 제공합니다.각 단계를 완료하고 실무 경험을 쌓기 위해 지침을 주의 깊게 따르세요. 과거 데이터에 따르면, 이것은 중급 레벨의 실험이며 완료율은 74%입니다.학습자들로부터 86%의 긍정적인 리뷰율을 받았습니다.

리터럴 텍스트 표현

문자열 리터럴은 프로그램에서 따옴표로 작성됩니다.

## Single quote
a = 'Yeah but no but yeah but...'

## Double quote
b = "computer says no"

## Triple quotes
c = '''
Look into my eyes, look into my eyes, the eyes, the eyes, the eyes,
not around the eyes,
don't look around the eyes,
look into my eyes, you're under.
'''

일반적으로 문자열은 단일 라인만 포함할 수 있습니다. 삼중 따옴표는 모든 서식을 포함하여 여러 줄에 걸쳐 묶인 모든 텍스트를 캡처합니다.

단일 (') 따옴표와 이중 (") 따옴표를 사용하는 것 사이에는 차이가 없습니다. 하지만 문자열을 시작하는 데 사용된 동일한 유형의 따옴표를 사용하여 문자열을 종료해야 합니다.

문자열 이스케이프 코드

이스케이프 코드는 제어 문자 및 키보드에서 직접 쉽게 입력할 수 없는 문자를 나타내는 데 사용됩니다. 다음은 몇 가지 일반적인 이스케이프 코드입니다.

'\n'      줄 바꿈 (Line feed)
'\r'      캐리지 리턴 (Carriage return)
'\t'      탭 (Tab)
'\''      리터럴 작은 따옴표 (Literal single quote)
'\"'      리터럴 큰 따옴표 (Literal double quote)
'\\'      리터럴 백슬래시 (Literal backslash)

문자열 표현

문자열의 각 문자는 내부적으로 정수인 소위 유니코드 "코드 포인트 (code-point)"로 저장됩니다. 다음 이스케이프 시퀀스를 사용하여 정확한 코드 포인트 값을 지정할 수 있습니다.

a = '\xf1'          ## a = 'ñ'
b = '\u2200'        ## b = '∀'
c = '\U0001D122'    ## c = '𝄢'
d = '\N{FOR ALL}'   ## d = '∀'

유니코드 문자 데이터베이스는 사용 가능한 모든 문자 코드에 대한 참조입니다.

문자열 인덱싱 (String Indexing)

문자열은 개별 문자에 접근하기 위해 배열처럼 작동합니다. 0 부터 시작하는 정수 인덱스를 사용합니다. 음수 인덱스는 문자열의 끝을 기준으로 한 위치를 지정합니다.

a = 'Hello world'
b = a[0]          ## 'H'
c = a[4]          ## 'o'
d = a[-1]         ## 'd' (end of string)

:를 사용하여 인덱스 범위를 지정하여 부분 문자열을 슬라이싱 (slicing) 하거나 선택할 수도 있습니다.

d = a[:5]     ## 'Hello'
e = a[6:]     ## 'world'
f = a[3:8]    ## 'lo wo'
g = a[-5:]    ## 'world'

종료 인덱스에 있는 문자는 포함되지 않습니다. 누락된 인덱스는 문자열의 시작 또는 끝을 가정합니다.

문자열 연산 (String operations)

연결, 길이, 멤버십 (membership) 및 반복.

## 연결 (+) (Concatenation (+))
a = 'Hello' + 'World'   ## 'HelloWorld'
b = 'Say ' + a          ## 'Say HelloWorld'

## 길이 (len) (Length (len))
s = 'Hello'
len(s)                  ## 5

## 멤버십 테스트 (`in`, `not in`) (Membership test (`in`, `not in`))
t = 'e' in s            ## True
f = 'x' in s            ## False
g = 'hi' not in s       ## True

## 반복 (s * n) (Replication (s * n))
rep = s * 5             ## 'HelloHelloHelloHelloHello'

문자열 메서드 (String methods)

문자열은 문자열 데이터를 사용하여 다양한 연산을 수행하는 메서드를 가지고 있습니다.

예시: 선행/후행 공백 제거.

s = '  Hello '
t = s.strip()     ## 'Hello'

예시: 대소문자 변환.

s = 'Hello'
l = s.lower()     ## 'hello'
u = s.upper()     ## 'HELLO'

예시: 텍스트 대체.

s = 'Hello world'
t = s.replace('Hello' , 'Hallo')   ## 'Hallo world'

더 많은 문자열 메서드:

문자열은 텍스트 데이터를 테스트하고 조작하기 위한 다양한 메서드를 가지고 있습니다. 다음은 메서드의 작은 예시입니다.

s.endswith(suffix)     ## 문자열이 suffix 로 끝나는지 확인
s.find(t)              ## s 에서 t 의 첫 번째 발생 위치
s.index(t)             ## s 에서 t 의 첫 번째 발생 위치
s.isalpha()            ## 문자가 알파벳인지 확인
s.isdigit()            ## 문자가 숫자인지 확인
s.islower()            ## 문자가 소문자인지 확인
s.isupper()            ## 문자가 대문자인지 확인
s.join(slist)          ## s 를 구분 기호로 사용하여 문자열 목록을 결합
s.lower()              ## 소문자로 변환
s.replace(old,new)     ## 텍스트 대체
s.rfind(t)             ## 문자열 끝에서부터 t 검색
s.rindex(t)            ## 문자열 끝에서부터 t 검색
s.split([delim])       ## 문자열을 부분 문자열 목록으로 분할
s.startswith(prefix)   ## 문자열이 prefix 로 시작하는지 확인
s.strip()              ## 선행/후행 공백 제거
s.upper()              ## 대문자로 변환

문자열 불변성 (String Mutability)

문자열은 "불변 (immutable)" 또는 읽기 전용입니다. 생성된 후에는 값을 변경할 수 없습니다.

>>> s = 'Hello World'
>>> s[1] = 'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>>

문자열 데이터를 조작하는 모든 연산과 메서드는 항상 새로운 문자열을 생성합니다.

문자열 변환 (String Conversions)

str()을 사용하여 모든 값을 문자열로 변환합니다. 결과는 print() 문에 의해 생성되었을 텍스트와 동일한 텍스트를 포함하는 문자열입니다.

>>> x = 42
>>> str(x)
'42'
>>>

바이트 문자열 (Byte Strings)

일반적으로 저수준 I/O 에서 사용되는 8 비트 바이트 문자열은 다음과 같이 작성됩니다.

data = b'Hello World\r\n'

첫 번째 따옴표 앞에 작은 b를 붙여서 텍스트 문자열이 아닌 바이트 문자열임을 지정합니다.

대부분의 일반적인 문자열 연산이 작동합니다.

len(data)                         ## 13
data[0:5]                         ## b'Hello'
data.replace(b'Hello', b'Cruel')  ## b'Cruel World\r\n'

인덱싱은 바이트 값을 정수로 반환하기 때문에 약간 다릅니다.

data[0]   ## 72 (ASCII code for 'H')

텍스트 문자열로/에서 변환.

text = data.decode('utf-8') ## bytes -> text
data = text.encode('utf-8') ## text -> bytes

'utf-8' 인수는 문자 인코딩을 지정합니다. 다른 일반적인 값으로는 'ascii''latin1'이 있습니다.

Raw 문자열 (Raw Strings)

Raw 문자열은 해석되지 않은 백슬래시를 가진 문자열 리터럴입니다. 소문자 "r"로 초기 따옴표를 접두사로 지정하여 정의합니다.

>>> rs = r'c:\newdata\test' ## Raw (uninterpreted backslash)
>>> rs
'c:\\newdata\\test'

문자열은 입력한 그대로, 안에 묶인 리터럴 텍스트입니다. 이는 백슬래시가 특별한 의미를 갖는 상황에서 유용합니다. 예: 파일 이름, 정규 표현식 등.

f-문자열 (f-Strings)

형식화된 표현식 대체가 있는 문자열입니다.

>>> name = 'IBM'
>>> shares = 100
>>> price = 91.1
>>> a = f'{name:>10s} {shares:10d} {price:10.2f}'
>>> a
'       IBM        100      91.10'
>>> b = f'Cost = ${shares*price:0.2f}'
>>> b
'Cost = $9110.00'
>>>

참고: Python 3.6 이상이 필요합니다. 형식 코드의 의미는 나중에 다룹니다.

이 연습에서는 Python 의 문자열 유형에 대한 연산을 실험해 볼 것입니다. 결과를 쉽게 확인할 수 있는 Python 대화형 프롬프트에서 이 작업을 수행해야 합니다. 중요한 참고 사항:

인터프리터와 상호 작용해야 하는 연습에서 >>>는 Python 이 새로운 문장을 입력하도록 할 때 나타나는 인터프리터 프롬프트입니다. 연습의 일부 문장은 여러 줄에 걸쳐 있습니다. 이러한 문장을 실행하려면 'return' 키를 몇 번 눌러야 할 수 있습니다. 이러한 예제를 작업할 때 >>>입력하지 않는다는 점을 다시 한번 알려드립니다.

다음과 같이 일련의 주식 종목 기호를 포함하는 문자열을 정의하는 것으로 시작합니다.

>>> symbols = 'AAPL,IBM,MSFT,YHOO,SCO'
>>>

연습 1.13: 개별 문자 및 부분 문자열 추출

문자열은 문자의 배열입니다. 몇 개의 문자를 추출해 보십시오.

>>> symbols[0]
?
>>> symbols[1]
?
>>> symbols[2]
?
>>> symbols[-1]        ## 마지막 문자
?
>>> symbols[-2]        ## 음수 인덱스는 문자열의 끝에서부터 시작합니다.
?
>>>

Python 에서 문자열은 읽기 전용입니다.

symbols의 첫 번째 문자를 소문자 'a'로 변경하려는 시도를 통해 이를 확인하십시오.

>>> symbols[0] = 'a'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>>

연습 1.14: 문자열 연결 (String concatenation)

문자열 데이터는 읽기 전용이지만, 항상 변수를 새로 생성된 문자열에 다시 할당할 수 있습니다.

새로운 기호 "GOOG"을 symbols의 끝에 연결하는 다음 문장을 시도해 보십시오.

>>> symbols = symbols + 'GOOG'
>>> symbols
'AAPL,IBM,MSFT,YHOO,SCOGOOG'
>>>

이런! 원하는 결과가 아닙니다. symbols 변수가 값 'AAPL,IBM,MSFT,YHOO,SCO,GOOG'를 갖도록 수정하십시오.

>>> symbols = ?
>>> symbols
'AAPL,IBM,MSFT,YHOO,SCO,GOOG'
>>>

문자열 앞에 'HPQ'를 추가하십시오.

>>> symbols = ?
>>> symbols
'HPQ,AAPL,IBM,MSFT,YHOO,SCO,GOOG'
>>>

이 예제에서는 문자열이 읽기 전용이라는 것을 위반하는 것처럼 보일 수 있지만, 원래 문자열이 수정되는 것처럼 보일 수 있습니다. 그렇지 않습니다. 문자열에 대한 연산은 매번 완전히 새로운 문자열을 생성합니다. 변수 이름 symbols가 다시 할당되면 새로 생성된 문자열을 가리킵니다. 그 후, 이전 문자열은 더 이상 사용되지 않으므로 파괴됩니다.

연습 1.15: 멤버십 테스트 (부분 문자열 테스트)

in 연산자를 사용하여 부분 문자열을 확인하는 실험을 해보십시오. 대화형 프롬프트에서 다음 연산을 시도해 보십시오.

>>> 'IBM' in symbols
?
>>> 'AA' in symbols
True
>>> 'CAT' in symbols
?
>>>

'AA'에 대한 확인이 왜 True를 반환했습니까?

연습 1.16: 문자열 메서드 (String Methods)

Python 대화형 프롬프트에서 몇 가지 문자열 메서드를 실험해 보십시오.

>>> symbols.lower()
?
>>> symbols
?
>>>

기억하세요, 문자열은 항상 읽기 전용입니다. 연산의 결과를 저장하려면 변수에 저장해야 합니다.

>>> lowersyms = symbols.lower()
>>>

몇 가지 더 많은 연산을 시도해 보십시오.

>>> symbols.find('MSFT')
?
>>> symbols[13:17]
?
>>> symbols = symbols.replace('SCO','DOA')
>>> symbols
?
>>> name = '   IBM   \n'
>>> name = name.strip()    ## Remove surrounding whitespace
>>> name
?
>>>

연습 1.17: f-문자열 (f-strings)

때로는 문자열을 생성하고 변수의 값을 문자열에 포함시키고 싶을 때가 있습니다.

그렇게 하려면 f-문자열을 사용하십시오. 예를 들어:

>>> name = 'IBM'
>>> shares = 100
>>> price = 91.1
>>> f'{shares} shares of {name} at ${price:0.2f}'
'100 shares of IBM at $91.10'
>>>

연습 1.10 의 mortgage.py 프로그램을 수정하여 f-문자열을 사용하여 출력을 생성하십시오. 출력이 보기 좋게 정렬되도록 시도하십시오.

연습 1.18: 정규 표현식 (Regular Expressions)

기본 문자열 연산의 한 가지 제한 사항은 고급 패턴 매칭 (pattern matching) 을 지원하지 않는다는 것입니다. 이를 위해서는 Python 의 re 모듈과 정규 표현식을 사용해야 합니다. 정규 표현식 처리는 큰 주제이지만, 다음은 간단한 예입니다.

>>> text = 'Today is 3/27/2018. Tomorrow is 3/28/2018.'
>>> ## Find all occurrences of a date
>>> import re
>>> re.findall(r'\d+/\d+/\d+', text)
['3/27/2018', '3/28/2018']
>>> ## Replace all occurrences of a date with replacement text
>>> re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text)
'Today is 2018-3-27. Tomorrow is 2018-3-28.'
>>>

re 모듈에 대한 자세한 내용은 공식 문서를 참조하십시오: https://docs.python.org/library/re.html.

해설 (Commentary)

인터프리터를 가지고 실험을 시작할 때, 다양한 객체에서 지원되는 연산에 대해 더 알고 싶어지는 경우가 많습니다. 예를 들어, 문자열에서 사용할 수 있는 연산은 어떻게 찾을 수 있을까요?

Python 환경에 따라 탭 자동 완성 (tab-completion) 을 통해 사용 가능한 메서드 목록을 볼 수 있습니다. 예를 들어, 다음을 입력해 보십시오.

>>> s = 'hello world'
>>> s.<tab key>
>>>

탭 키를 눌러도 아무런 반응이 없다면, 내장 함수인 dir() 함수를 사용할 수 있습니다. 예를 들어:

>>> s = 'hello'
>>> dir(s)
['__add__', '__class__', '__contains__', ..., 'find', 'format',
'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace',
'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition',
'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit',
'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase',
'title', 'translate', 'upper', 'zfill']
>>>

dir()(.) 다음에 나타날 수 있는 모든 연산 목록을 생성합니다. 특정 연산에 대한 자세한 정보를 얻으려면 help() 명령을 사용하십시오.

>>> help(s.upper)
Help on built-in function upper:

upper(...)
    S.upper() -> string

    Return a copy of the string S converted to uppercase.
>>>

요약 (Summary)

축하합니다! 문자열 (Strings) 랩을 완료했습니다. LabEx 에서 더 많은 랩을 연습하여 실력을 향상시킬 수 있습니다.