Ir para o conteúdo

Cadeia de Caracteres

Manipulação de cadeia de caracteres

>>> s = 'Isso é uma cadeia de caracteres'
>>> s.split()
['Isso', '\xc3\xa9', 'uma', 'cadeia', 'de', 'caracteres']
>>> 'Isso' in s
True
>>> s.find('de')
14
>>> ', '.join(s.split())
'Isso, \xc3\xa9, uma, cadeia, de, caracteres'

A manipulação das cadeias de caracteres é a chave para a interpretação do conteúdo de arquivos.

  • Texto em Python é representado pelas cadeias de caracteres;
  • Inspecionar e manipular essas cadeias é o caminho para entender o conteúdo de arquivos;
  • Plano: primeiro operações básicas, depois exemplos reais.

Um exemplo para ilustração:

>>> s = u'Berlim: 18.4 C\u2070 às 16h'

Veja mais

Veja mais códigos unicode para caracteres aqui

As cadeias de caracteres se comportam como tuplas (listas imutáveis):

>>> s[0]
'B'
>>> s[1]
'e'
>>> s[-1]
'h'

Extraindo partes de cadeia de caracteres

Partes de cadeias de caracteres podem ser obtidas da mesma forma que os cortes em listas:

>>> s
'Berlim: 18.4 C às 16h'
>>> s[8:]     ## do indice 8 ao final da cadeia de caracteres
'18.4 C às 16h'
>>> s[8:12]   ## indice 8, 9, 10 e 11 (não 12!)
'18.4'
>>> s[8:-1]
'18.4 C às 16'
>>> s[8:-8]
'18.4 C'

Achando o ínicio de um texto na cadeia de caracteres:

>>> s.find('Berlim')  ## onde 'Berlim' inicia?
0                     ## no indice 0
>>> s.find('h')
21
>>> s.find('Oslo')    ## não encontrado
-1

Checando se um texto está contido em uma cadeia de caracteres

>>> 'Berlim' in s:
True
>>> 'Oslo' in s:
False

>>> if 'C' in s:
...     print 'C achado'
... else:
...     print 'nenhum C'
...
C achado

Substituindo um texto por outro

Sintaxe:

s.replace(s1, s2): substitui s1 por s2
>>> s.replace(' ', '__')
'Berlim:__18.4__C__às__4h'
>>> s.replace('Berlim', 'Curitiba')
'Curitiba: 18.4 C às 4h'

Exemplo: substituindo o texto antes dos dois pontos

>>> s
'Berlim: 18.4 C às 4h'
>>> s.replace(s[:s.find(':')], 'Curitiba')
'Curitiba: 18.4 C às 4h'
  1. s.find(':') retorna 6;
  2. s[:6] é Berlim;
  3. Berlim é substituido por Curitiba.

Dividindo uma cadeia de caracteres em uma lista de subtextos

s.split(arg) divide em uma lista de subtextos separados pelo argumento arg. Exemplo:

>>> s
'Berlim: 18.4 C às 16h'
>>> s.split(':')
['Berlim', ' 18.4 C \xc3\xa0s 16h']
>>> s.split()
['Berlim:', '18.4', 'C', '\xc3\xa0s', '16h']

Tente endenter esse:

>>> s.split(':')[1].split()[0]
'18.4'
>>> deg = float(_)  ## _ representa o último resultado no console
>>> deg
18.4

Dividindo uma cadeia de caracteres em linhas

Normalmente, os arquivos de dados contém muito texto e queremos separá-lo em linhas. Linhas podem ser separadas por diferentes caracteres de controle em diferentes plataformas:

  • \n no Unix/Linux/Mac
  • \r\n no windows
>>> t = '1a linha\n2a linha\n3a linha'     ## linha Unix
>>> print t
1a linha
2a linha
3a linha
>>> t.split('\n')
['1a linha', '2a linha', '3a linha']
>>> t.splitlines()
['1a linha', '2a linha', '3a linha']
>>> t = '1a linha\r\n2a linha\r\n3a linha' ## Windows
>>> t.split('\n')
['1a linha\r', '2a linha\r', '3a linha']   ## não é o resultado esperado!
>>> t.splitlines()                         ## qualquer plataforma!
['1a linha', '2a linha', '3a linha']

Cadeias de caracteres são objetos imutáveis

Não é possível modificar uma cadeia de caracteres (da mesma forma que as listas). Todas as modificações resultam em uma nova cadeia de caracteres.

>>> s[18] = 5
...
TypeError: 'str' object does not support item assignment

>>> ## criando uma nova cadeia de caracteres e adicionando partes de s:
>>> s2 = s[:19] + '5' + s[21:]
>>> s2
'Berlim: 18.4 C às 5h'

Removendo espaços em branco

>>> s = '   texto com espaços em branco antes e depois   \n'
>>> s.strip()
'texto com espaços em branco antes e depois'
>>> s.lstrip()   ## removendo da esquerda
'texto com espaços em branco antes e depois   \n'
>>> s.rstrip()   ## removendo da direita
'   texto com espaços em branco antes e depois'

Algumas funções convenientes para cadeias de caracteres

>>> '214'.isdigit()
True
>>> '  214 '.isdigit()
False
>>> '2.14'.isdigit()
False

>>> s.lower()
'berlim: 18.4 c às 4h'
>>> s.upper()
'BERLIM: 18.4 C ÀS 4H'

>>> s.startswith('Berlim')
True
>>> s.endswith('min')
False

>>> '    '.isspace()   ## espaços em branco
True
>>> '  \n'.isspace()   ## nova linha
True
>>> '  \t '.isspace()  ## TAB
True
>>> ''.isspace()       ## cadeia de caracteres vazia
False

Unindo cadeias de caracteres

Podemos unir uma lista de cadeias de caracteres para uma única cadeia:

>>> strings = ['Newton', 'Secante', 'Bisecção']
>>> ', '.join(strings)
'Newton, Secante, Bisecção'

As operações inversas seriam:

t = delimitador.join(listaCadeias)
listaCadeias = t.split(delimitador)

Eliminando as duas primeiras palavras em uma linha:

>>> linha = 'Esta é uma linha com palavras separadas por espaços'
>>> palavras = linha.split()
>>> linha2 = ' '.join(palavras[2:])
>>> print linha2
'uma linha com palavras separadas por espaços'

Lendo pares de números (x,y) de um arquivo

Arquivo de exemplo:

(1.3,0)    (-1,2)    (3,-1.5)
(0,1)      (1,0)     (1,1)
(0,-0.01)  (10.5,-1) (2.5,-2.5) 

Algoritmo:

  1. Leia linha por linha;
  2. Divida cada linha em palavras;
  3. Em cada palavra, remova o parênteses e divida o resto na vírgula.

O código:

linhas = open('ler_pares.dat', 'r').readlines()

pares = []   ## lista de (n1, n2) pares de números
for linha in linhas:
    palavras = linha.split()
    for palavra in palavras:
        palavra = palavra[1:-1]  ## removendo o parênteses
        n1, n2 = palavra.split(',')
        n1 = float(n1);  n2 = float(n2)
        par = (n1, n2)
        pares.append(par)

Lista resultante em Python:

\[(1.3, 0.0),
 (-1.0, 2.0),
 (3.0, -1.5),
 (0.0, 1.0),
 (1.0, 0.0),
 (1.0, 1.0),
 (0.0, -0.01),
 (10.5, -1.0),
 (2.5, -2.5)\] 

Solução alternativa: sintaxe Python no formato do arquivo

Suponha que o formato do arquivo

(1.3, 0)    (-1, 2)    (3, -1.5)
...

Seja um pouco diferente:

\[(1.3, 0),    (-1, 2),    (3, -1.5),
...
\]

Chamando a função eval no formato diferente, é possível obter a lista final diretamente:

linhas = open('ler_pares.dat', 'r').readlines()

texto = open('ler_pares2.dat', 'r').read()
texto = '[' + texto.replace(')', '),') + ']'
pares = eval(texto)