2012-05-21 9 views
10

Si consideri il seguente comando:C'è un modo per cancellare completamente i campi in awk, in modo che i delimitatori extra non vengano stampati?

gawk -F"\t" "BEGIN{OFS=\"\t\"}{$2=$3=\"\"; print $0}" Input.tsv 

Quando ho creato $ 2 = $ 3 = "", l'effetto desiderato per ottenere lo stesso effetto di scrittura:

print $1,$4,$5...$NF 

Tuttavia, ciò che in realtà accade è che ho ottenere due campi vuoti, con i delimitatori di campo aggiuntivi ancora in stampa.

È possibile eliminare effettivamente $ 2 e $ 3?

Nota: se questo era su Linux in bash, l'istruzione corretta sopra sarebbe la seguente, ma Windows non gestisce le virgolette singole in cmd.exe.

gawk -F'\t' 'BEGIN{OFS="\t"}{$2=$3=""; print $0}' Input.tsv 
+2

Si dovrebbe utilizzare le virgolette singole per il set esterno, allora non c'è bisogno di fuggire i doppi apici all'interno dello script. Se si utilizzano le virgolette doppie per il set esterno in modo da poter incorporare le variabili di shell, utilizzare '-v' per eseguire il passaggio di variabili. –

+0

Sto usando awk in Windows. Cmd.exe non funziona bene con le virgolette singole per qualche motivo. – merlin2011

+0

L'ho fatto più di 10 anni fa (credo). prova a fare un '$ 2 = $ 3 =" "; $ 0 = $ 0'. In bocca al lupo. – shellter

risposta

4

Questo è un vecchietto ma goodie.

Come sottolinea Jonathan, non è possibile eliminare i campi nel mezzo, ma è possibile sostituirli con i contenuti di altri campi. E puoi fare una funzione riutilizzabile per gestire la cancellazione per te.

$ cat test.awk 
function rmcol(col,  i) { 
    for (i=col; i<NF; i++) { 
    $i=$(i+1) 
    } 
    NF-- 
} 

{ 
    rmcol(3) 
} 

1 

$ printf 'one two three four\ntest red green blue\n' | awk -f test.awk 
one two four 
test red blue 
3

Se stai solo cercando di rimuovere le colonne, è possibile utilizzare cut:

cut -f 1,4- file.txt

emulare cut:

awk -F "\t" '{ for (i=1; i<=NF; i++) if (i != 2 && i != 3) { if (i == NF) printf $i"\n"; else printf $i"\t" } }' file.txt

analogo:

awk -F "\t" '{ delim =""; for (i=1; i<=NF; i++) if (i != 2 && i != 3) { printf delim $i; delim = "\t"; } printf "\n" }' file.txt

HTH

+0

L'ultimo esempio stampa una scheda finale. '{for (...) {printf delim $ i; delim = "\ t"}; printf "\ n"} ' –

+0

Sono preoccupato per il gsub perché ci sono altri campi che sono legittimamente vuoti e voglio i delimitatori multipli. – merlin2011

+0

@DennisWilliamson Grazie per le correzioni. – Steve

7

Non è possibile eliminare i campi in mezzo, ma è possibile eliminare i campi, alla fine, decrementando NF.

in modo da poter spostare tutti i campi successivi fino a sovrascrivere $2 e $3 poi decrementare NF a due, che cancella gli ultimi due campi:

$ echo 1 2 3 4 5 6 7 | awk '{for(i=2; i<NF-1; ++i) $i=$(i+2); NF-=2; print $0}' 
1 4 5 6 7 
1

Un modo potrebbe essere quello di rimuovere i campi come si fa e rimuovere spazi aggiuntivi con gsub:

awk 'BEGIN { FS = "\t" } { $2 = $3 = ""; gsub(/\s+/, "\t"); print }' input-file 
1

In aggiunta della risposta da Suicidal Steve mi piacerebbe suggerire una soluzione in più, ma utilizzando sed invece awk.

Sembra più complicato dell'uso del taglio come suggerito da Steve. Ma è stata la soluzione migliore perché sed -i consente la modifica sul posto.

sed -i 's/\(.*,\).*,.*,\(.*\)/\1\2/' FILENAME 
0

L'unico modo che posso pensare di farlo in Awk senza l'utilizzo di un ciclo è quello di utilizzare gsub su $0 combinare adiacente FS:

$ echo {1..10} | awk '{$2=$3=""; gsub(FS"+",FS); print}' 
1 4 5 6 7 8 9 10 
-1
echo one two three four five six|awk '{ 
print $0 
is3=$3 
$3="" 
print $0 
print is3 
}' 

uno due tre quattro cinque sei

uno due quattro cinque sei

tre

0

bene, se l'obiettivo è quello di rimuovere i delimitatori in più quindi è possibile utilizzare " tr "su Linux. Esempio:

$ echo "1,2 ,,, 5" | tr -s ''

1,2,5

Problemi correlati