2010-02-05 17 views
8

ecco la mia situazione: avevo un grande file di testo che volevo ottenere da alcune informazioni. Ho usato sed per estrarre tutte le informazioni rilevanti basate su regexp, ma ogni "pezzo" di informazioni che ho estratto è su una riga separata, vorrei che ogni "record" fosse sulla sua stessa riga in modo che potesse essere facilmente importato in un DB.
Ecco un esempio dei miei dati in questo momento:Uso di awk (o sed) per rimuovere i newline in base al primo carattere della riga successiva

92831.499.000
, 0644321
79217.999.000
, 5.417.178
, PK91622
, PK90755

Idealmente, Vorrei che questo risultato assomigliasse:

92831,499,000 , 0644321
79217.999.000 , 5.417.178 , PK91622
79217.999.000 , 5.417.178 , PK90755

Questo può essere più difficile da fare, quindi mi accontenterei perché l'uscita di quell'ultimo "record" compaia una sola volta con l'ulteriore "PK ..." per essere il 4 ° "campo" di quella linea.
Alla fine, il modo più semplice che potrei pensare di fare è se la linea inizia con una virgola (^,) la nuova riga prima che dovrebbe essere rimossa ... Non ho molta familiarità con awk anche se così si potrebbe dare un inizio su questo sarebbe davvero apprezzato! Grazie!

risposta

2

Beh, suppongo che avrei dovuto dare un'occhiata più da vicino all'utilizzo di Records in awk quando stavo cercando di capirlo la scorsa notte ... 10 minuti dopo averli guardati, ho funzionato. Per chiunque sia interessato ecco come ho fatto questo: Nella mia sceneggiatura originale di sed ho inserito un nuovo extrafront all'inizio dell'inizio di ogni record, quindi ora c'è una riga vuota che li separa. Quindi utilizzo il seguente comando awk:

awk 'BEGIN {RS = ""; FS = "\ n"}
{
se (NF> = 3)
for (i = 3; i < = NF; i ++)
print $ 1, $ 2, $ i
}'

e funziona come un fascino che emette esattamente come volevo!

+0

+1 a volte semplice programma> regex – gbarry

1
sedsed -d -n ':t;/^,/!x;H;n;/^,/{x;$!bt;x;H};x;s/\n//g;p;${x;/^,/!p}' filename 
1

Senza campo involucro speciale 3, facile.

awk ' 
    !/^,/ { if (NR > 1) print x ; x = $0 } 
    /^,/ { x = x OFS $0 } 
    END  { if (NR) print x } 
' 

Con, più complesso ma ancora non troppo difficile.

awk ' 
    !/^,/ { if (n && n < 3) print x ; x = $0 ; n = 1 } 
    /^,/ { if (++n > 2) { print x, $0 } else { x = x OFS $0 } } 
    END  { if (n && n < 3) print x } 
' 
5
 
$ perl -0pe 's/\n,/,/g' < test.dat 
92831,499,000,0644321 
79217,999,000,5417178,PK91622,PK90755 

Traduzione: Read sfuso senza separazione linea, scambiare fuori ogni virgola che segue una nuova riga con solo una virgola.

Codice più breve qui!

1

Questo potrebbe funzionare per voi:

# sed ':a;N;s/\n,/,/;ta;P;D' test.dat | sed 's/,/\n/5;s/\(.*,\).*\n/&\1/' 
92831,499,000,0644321 
79217,999,000,5417178,PK91622 
79217,999,000,5417178,PK90755 

Spiegazione:

Questo è disponibile in due parti:

Aggiungere la riga successiva e poi se la linea allegata inizia con un ,, eliminare il nuova riga incorporata \n e ricominciare. Se non si stampa fino alla nuova riga e quindi si cancella fino alla nuova riga. Ripetere.

Sostituire il 5 , con una nuova riga. Quindi inserire i primi quattro campi tra la nuova riga incorporata e il sesto campo.