2013-07-02 12 views
5

Sto lavorando con trasferimenti di file tra server registrati. Questi alla fine devono essere caricati su un database, quindi li sto preelaborando per verificare la presenza di errori. Ogni voce del file di registro rappresentava un trasferimento e sono del formato:Divisione di una stringa contenente coppie "chiave = valore" delimitate da spazio quando il valore può contenere anche spazio

key1=value1 key2=value2 

per un totale di 16 campi. La maggior parte dei trasferimenti va bene, tranne quando qualcuno trasferisce un file che ha un nome con uno spazio al suo interno. Questo rovina la mia elaborazione perché chiamo semplicemente split on space nel mio script perl. Esempio:

DATE=20130411140806.384553 HOST=somehost PROG=someserver NL.EVNT=FTP_INFO START=20130411140806.384109 USER=someuser FILE=/extended_path/Wallpapers Folder.ico BUFFER=98720 BLOCK=262144 NBYTES=0 VOLUME=/ STREAMS=2 STRIPES=1 DEST=[0.0.0.0] TYPE=STOR CODE=226 

Questo è solo un esempio in cui c'è uno spazio tra "Wallpapers" e "Folder.ico". C'è un modo per progettare un'espressione regolare che possa tener conto di ciò e suddividere tutte quelle coppie di valori-chiave? Se non esiste un modo regolare per farlo, potresti suggerire un altro modo per gestirlo?

Il mio obiettivo è sostituire quegli spazi con niente (ovvero rimuovere lo spazio) o un trattino basso in modo che quando eseguo lo script per il caricamento nel database, non si verificherà alcun problema semplicemente suddividendolo in uno spazio singolo. Sto usando perl per fare tutto questo a proposito.

+0

Potete sempre contare su quei campi in questo ordine? –

+0

Suggerisco di aggiungere valori come stringhe tra virgolette, o tutti i valori o almeno quelli che contengono spazi bianchi. – 0xCAFEBABE

+0

@DanielGimenez Sì. È registrato dal server. – shaun

risposta

9

È possibile cercare gli spazi indesiderati utilizzando un lookahead che assicura che non prec una chiave:

$input =~ s/[ ](?!\S+=)/_/g; 

Il lookahead fa in modo che non v'è alcun = prima del prossimo carattere di spazio.

Quindi è possibile dividere gli spazi.

In alternativa, per abbinare subito, è possibile utilizzare una tecnica simile:

while ($input =~ m/(\S+)=((?:\S|[ ](?!\S+=))+)/g) 
{ 
    # $1 is the key 
    # $2 is the value 
} 

Per il valore che ripetere sia caratteri non-spazio o gli spazi che non prec una chiave.

Working demo.

se le chiavi sono sempre in maiuscolo, è possibile sostituire tutti \S+ nel mio codice con [A-Z]+.

+0

+1 sulla regex. Non potrei essere così conciso come una soluzione. Buon uso di spazi vuoti negati. –

+0

Grazie mille Sir! Ha funzionato davvero bene. – shaun

Problemi correlati