2016-04-30 17 views
10

Ho un file .txt (raschiato come pre-formattato il testo da un sito web) in cui i dati si presenta così:Rimozione spazio bianco da txt con Python

B, NICKOLAS      CT144531X  D1026 JUDGE ANNIE WHITE JOHNSON 
ANDREWS VS BALL     JA-15-0050  D0015 JUDGE EDWARD A ROBERTS   

mi piacerebbe rimuovere tutti gli spazi in eccesso (sono in realtà un numero diverso di spazi, non tabulazioni) tra le colonne. Mi piacerebbe anche allora piace di sostituirlo con qualche delimitatore (scheda o tubo dal momento che c'è virgole all'interno dei dati), in questo modo:

ANDREWS VS BALL|JA-15-0050|D0015|JUDGE EDWARD A ROBERTS 

sono guardato intorno e ha scoperto che le migliori opzioni stanno usando regex o shlex per dividere. Due scenari simili:

+1

C'è sempre più di uno spazio tra le colonne di dati? –

+0

@ cricket_007 sì, sempre più di uno spazio – aysha

+0

Non si dovrebbe usare regex, perché i dati potrebbero avere 2 o più spazi in una colonna. I dati sono in un formato tabella di testo, le colonne sp devono essere determinate dalla posizione di un carattere su ciascuna riga. –

risposta

5
s = """B, NICKOLAS      CT144531X  D1026 JUDGE ANNIE WHITE JOHNSON 
ANDREWS VS BALL     JA-15-0050  D0015 JUDGE EDWARD A ROBERTS 
""" 

# Update 
re.sub(r"(\S)\ {2,}(\S)(\n?)", r"\1|\2\3", s) 
In [71]: print re.sub(r"(\S)\ {2,}(\S)(\n?)", r"\1|\2\3", s) 
B, NICKOLAS|CT144531X|D1026|JUDGE ANNIE WHITE JOHNSON 
ANDREWS VS BALL|JA-15-0050|D0015|JUDGE EDWARD A ROBERTS 
+0

Alla fine si aggiunge un tubo aggiuntivo. –

+0

Aggiornato, ora chiaro risultato – Janom

+0

Perfetto! Pulito e semplice, in più aggiunge le interruzioni di riga piacevolmente. – aysha

3

considerando che ci sono almeno due spazi che separano le colonne, è possibile utilizzare questo:

lines = [ 
'B, NICKOLAS      CT144531X  D1026 JUDGE ANNIE WHITE JOHNSON ', 
'ANDREWS VS BALL     JA-15-0050  D0015 JUDGE EDWARD A ROBERTS  ' 
] 

for line in lines: 
    parts = [] 
    for part in line.split(' '): 
     part = part.strip() 
     if part: # checking if stripped part is a non-empty string 
      parts.append(part) 
    print('|'.join(parts)) 

di uscita per il vostro input:

B, NICKOLAS|CT144531X|D1026|JUDGE ANNIE WHITE JOHNSON 
ANDREWS VS BALL|JA-15-0050|D0015|JUDGE EDWARD A ROBERTS 
+1

Il test è stato eseguito prima della pubblicazione come risposta? –

+0

Come può questo dare 'ANDREWS VS BALL | JA-15-0050 | D0015 | GIUDICE EDWARD A ROBERTS'? –

+0

cura di spiegare il downvote? @PeterWood Il codice modificato fornisce l'output richiesto. –

6

Che dire di questo?

your_string ='ANDREWS VS BALL     JA-15-0050  D0015 JUDGE EDWARD A ROBERTS' 
print re.sub(r'\s{2,}','|',your_string.strip()) 

uscita:

ANDREWS VS BALL|JA-15-0050|D0015|JUDGE EDWARD A ROBERTS 

expanation:

Ho usato re.sub() che prende 3 parametri, un modello, una stringa che si desidera sostituire con la stringa e si vuole lavorare su .

Quello che ho fatto è prendere almeno due spazi insieme, li ho sostituiti con uno | e lo ho applicato sulla stringa.

7

È possibile applicare la regex '\s{2,}' (due o più caratteri di spaziatura) a ogni riga e sostituire le corrispondenze con un singolo carattere '|'.

>>> import re 
>>> line = 'ANDREWS VS BALL     JA-15-0050  D0015 JUDGE EDWARD A ROBERTS  ' 
>>> re.sub('\s{2,}', '|', line.strip()) 
'ANDREWS VS BALL|JA-15-0050|D0015|JUDGE EDWARD A ROBERTS' 

Spogliarello qualsiasi spazi iniziali e finali dalla linea prima di applicare re.sub assicura che non sarà possibile ottenere '|' personaggi all'inizio e alla fine della linea.

tuo codice vero e proprio dovrebbe essere simile a questo:

import re 
with open(filename) as f: 
    for line in f: 
     subbed = re.sub('\s{2,}', '|', line.strip()) 
     # do something here 
+0

Grazie, davvero ben spiegato. Serve solo per aggiungere una funzione di interruzione di riga. – aysha

3

Sembra che i dati sono in un formato "text-table".

Si consiglia di utilizzare la prima riga per calcolare il punto iniziale e la lunghezza di ogni colonna (a mano o scrivere uno script con regex per determinare le colonne probabili), quindi scrivere uno script per iterare le righe del file, suddividere la riga in segmenti di colonna e applicare la striscia a ciascun segmento.

Se si utilizza un'espressione regolare, è necessario tenere traccia del numero di colonne e generare un errore se una determinata riga ha più del numero previsto di colonne (o un numero diverso rispetto al resto). La suddivisione in due o più spazi si interromperà se il valore di una colonna ha due o più spazi, il che non è solo del tutto possibile, ma anche probabile. Le tabelle di testo come questa non sono progettate per essere divise in un'espressione regolare, sono progettate per essere suddivise nelle posizioni dell'indice della colonna.

In termini di salvataggio dei dati, è possibile utilizzare il modulo csv per scrivere/leggere in un file csv. Ciò ti consentirà di gestire le virgolette e i caratteri di escape meglio di specificare un delimitatore. Se una delle tue colonne ha un valore | come valore, a meno che tu non stia codificando i dati con una strategia che gestisca gli escape oi valori letterali quotati, l'output si interromperà in lettura.

Analisi del testo di cui sopra sarebbe simile a questa (i annidati la comprensione lista con staffe al posto del tradizionale formato in modo che sia più facile da capire):

cols = ((0,34), 
     (34, 50), 
     (50, 59), 
     (59, None), 
     ) 
for line in lines: 
    cleaned = [i.strip() for i in [line[s:e] for (s, e) in cols]] 
    print cleaned 

allora si può scrivere con qualcosa di simile:

import csv 
with open('output.csv', 'wb') as csvfile: 
    spamwriter = csv.writer(csvfile, delimiter='|', 
          quotechar='"', quoting=csv.QUOTE_MINIMAL) 
    for line in lines: 
     spamwriter.writerow([line[col_start:col_end].strip() 
          for (col_start, col_end) in cols 
          ]) 
Problemi correlati