AWK – stampa lintervallo di colonne

se ho un file csv nel seguente formato:

column1,column2,column3,column4,column5,column6,column7,column8 

e desidero che awk stampi solo le colonne dalla 2 alla 7, utilizzerei:

awk -F"," "{print $2 "," $3 "," $4 "," $5 "," $6 "," $7}" file.csv 

e get:

column2,column3,column4,column5,column6,column7 

cè un modo per concatenare le colonne 2-7 per semplificare il comando. Dato che sto pensando a un file con un po più di colonne, il mio comando awk diventerebbe orribilmente lungo.

Commenti

  • vuoi sempre un insieme consecutivo di colonne (ad esempio 2-7, o 5-15 o altro)? In tal caso, puoi utilizzare un ciclo per stampare le colonne. In caso contrario, lì ' non evita di elencare le singole colonne che desideri (anche se puoi mescolare in alcuni loop dove necessario). Inoltre, quante colonne?
  • Infine, potresti volere considerare un linguaggio come perl o python con un buon parser CSV … specialmente se hai i nomi delle colonne nella prima riga (molti dei moduli di analisi CSV di perl ' possono usare questi per costruire un hash con i nomi delle colonne come chiavi. i ' m abbastanza sicuro che i parser CSV di python ' possano fare lo stesso). ha anche eccellenti operatori di splicing hash array &.
  • @cas sì, le colonne sarebbero sempre è consecutivo.
  • Questo risponde alla tua domanda? Stampa lintervallo di colonne separate da virgole e il resto senza virgole

Risposta

$ awk -v b=2 -v e=7 "BEGIN{FS=OFS=","} {for (i=b;i<=e;i++) printf "%s%s", $i, (i<e ? OFS : ORS)}" file column2,column3,column4,column5,column6,column7 

b = numero del campo iniziale, e = numero del campo finale. Se devi gestire i file CSV con campi tra virgolette, virgole incorporate, nuove righe e così via, consulta https://stackoverflow.com/q/45420535/1745001 .

Answer

Lutility cut ha una notazione compatta:

cut -d, -f2-7 <input-file> 

producendo:

colonna2, colonna3, colonna4, colonna5, colonna6, colonna7

Rispondendo al commento di @PlasmaBinturong: il mio intento era affrontare il problema di una breve sequenza di chiamate: " … il mio comando awk sarebbe diventato orribilmente lungo … ". Tuttavia, si possono anche trovare codici che dispongono i campi come si potrebbe desiderare. Per quanto mi piacciano awk, perl, python, ho spesso trovato utile creare unutilità specifica per estendere le capacità dello standard * nix. Quindi ecco un estratto da uno script di test, s2, che mostra le utilità ritagliare e sistemare, entrambi consentono la riorganizzazione e la duplicazione, con la disposizione che consente anche la riduzione degli intervalli di campo:

FILE=${1-data1} # Utility functions: print-as-echo, print-line-with-visual-space. pe() { for _i;do printf "%s" "$_i";done; printf "\n"; } pl() { pe;pe "-----" ;pe "$*"; } pl " Input data file $FILE:" head $FILE pl " Results, cut:" cut -d, -f2-7 $FILE pl " Results, recut (modified as my-recut):" my-recut -d "," 7,6,2-5 < $FILE pl " Results, arrange:" arrange -s "," -f 5,3-1,7,5,3-4,5 $FILE 

producendo risultati da queste versioni:

OS, ker|rel, machine: Linux, 3.16.0-10-amd64, x86_64 Distribution : Debian 8.11 (jessie) bash GNU bash 4.3.30 cut (GNU coreutils) 8.23 recut - ( local: RepRev 1.1, ~/bin/recut, 2010-06-10 ) arrange (local) 1.15 ----- Input data file data1: column1,column2,column3,column4,column5,column6,column7,column8 ----- Results, cut: column2,column3,column4,column5,column6,column7 ----- Results, recut (modified as my-recut): column7,column6,column2,column3,column4,column5 ----- Results, arrange: column5,column3,column2,column1,column7,column5,column3,column4,column5 

Il mio-recut è una leggera modifica del codice di textutils recut, e arrangiare è la nostra versione di un taglio esteso . Ulteriori informazioni:

recut Process fields like cut, allow repetitions and re-ordering. (what) Path : ~/bin/recut Version : - ( local: RepRev 1.1, ~/bin/recut, 2010-06-10 ) Length : 56 lines Type : Perl script, ASCII text executable Shebang : #!/usr/bin/perl Home : http://www1.cuni.cz/~obo/textutils/ (doc) Modules : (for perl codes) Getopt::Long 2.42 arrange Arrange fields, like cut, but in user-specified order. (what) Path : ~/bin/arrange Version : 1.15 Length : 355 lines Type : Perl script, ASCII text executable Shebang : #!/usr/bin/perl Modules : (for perl codes) warnings 1.23 strict 1.08 Carp 1.3301 Getopt::Euclid 0.4.5 

I migliori auguri … ciao, drl

Commenti

  • A differenza di Awk, restituisce le colonne nellordine del file di input, non nellordine del comando.
  • @PlasmaBinturong – vedi risposta modificata … acclamazioni

Risposta

sed -e " s/,/\n/7 ;# tag the end of col7 s/^/,/ ;# add a comma s/,/\n/2 ;# tag beginning of col2 s/.*\n\(.*\)\n.*/\1/ ;# perform surgery " file.csv 

Risultati:

column2,column3,column4,column5,column6,column7 

Risposta

Testato con il comando seguente e ha funzionato bene

awk -F "," "OFS=","{$1="";$NF="";print $0}" o| sed "s/^,//g"|sed "s/,$//g" 

output

column2,column3,column4,column5,column6,column7 

Commenti

  • grazie per la risposta, funziona bene senza " o " prima del primo sed pipe 🙂 si potevano concatenare i due comandi sed in uno: sed "s/^,//g; s/,$//g"
  • Perché stai testando il risultato dellesecuzione di

per decidere se stampare o meno la riga? Ci sono anche altri problemi (ad esempio NON hai bisogno di pipe per i comandi sed quando ' stai usando awk!) Ma quella parte di test OFS non ha assolutamente senso …

  • @EdMorton I ' spero ancora in un unico awk sollution …
  • @nath why ? Che cosa ' non va con la cut soluzione che @drl ha pubblicato ?
  • @EdMorton no hai ragione, funziona bene. Ho pensato che non potesse essere troppo complicato con awk ed ero curioso piuttosto per la questione di interesse che per un motivo tecnico 🙂
  • Lascia un commento

    Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *