2012-05-21 10 views
10

Rozważmy następującą komendę:Czy istnieje sposób całkowitego usunięcia pól w awk, aby dodatkowe ograniczniki nie były drukowane?

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

Kiedy ustawić $ 2 = $ 3 = "", efekt zamierzony, aby uzyskać taki sam efekt, jak pisanie:

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

Jednak to, co naprawdę się dzieje, że ja uzyskać dwa puste pola, a dodatkowe ograniczniki pól nadal drukują.

Czy można rzeczywiście usunąć 2 USD i 3 USD?

Uwaga: Jeśli był on pod Linuksem w bash, poprawne powyższe zdanie byłoby następujące, ale system Windows nie obsługuje pojedynczych cudzysłowów dobrze w cmd.exe.

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

należy używać apostrofów dla zewnętrznego zestawu, wtedy nie trzeba uciekać się cudzysłów wewnątrz skryptu. Jeśli używasz podwójnych cudzysłowów dla zewnętrznego zestawu, aby można było osadzić zmienne powłoki, użyj '-v', aby zamiast tego przekazywać zmienną. –

+0

Używam awk w systemie Windows. Program Cmd.exe nie jest z jakiegoś powodu dobrze odtwarzany z pojedynczymi cudzysłowami. – merlin2011

+0

Zrobiłem to 10 lat temu (myślę). spróbuj wykonać "$ 2 = 3 $ =" "; 0 $ = 0 $". Powodzenia. – shellter

Odpowiedz

4

To staruszek, ale jare.

Jak wskazuje Jonathan, nie można usuwać pól w środku, ale można zastąpić ich zawartość treścią innych pól. Możesz też użyć funkcji wielokrotnego użytku, aby obsłużyć usunięcie.

$ 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

Jeśli szukasz po prostu usunąć kolumny, można użyć cut:

cut -f 1,4- file.txt

naśladować 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

podobne:

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

Ostatni przykład wyświetla zakładkę końcową. '{for (...) {printf delim $ i; delim = "\ t"}; printf "\ n"} ' –

+0

Martwię się o gsub, ponieważ istnieją inne pola, które są prawnie puste i chcę mieć wiele ograniczników. – merlin2011

+0

@DennisWilliamson Dziękuję za poprawki. – Steve

7

Nie można usunąć pola w środku, ale można usunąć pola na końcu, przez zmniejszanie NF.

Więc można przesunąć wszystkie nowsze pola aż do nadpisania $2 i $3 następnie zmniejszyć NF przez dwa, które kasuje ostatnie dwa pola:

$ 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

Jednym ze sposobów mogłoby być usunięcie pola tak jak ty i usunąć dodatkowe przestrzenie z gsub:

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

W dodaniem odpowiedź Suicidal Steve które chciałbym zaproponować jeszcze jedno rozwiązanie, ale stosując zamiast sed awk.

Wydaje się bardziej skomplikowane niż użycie cięcia, jak sugerował to Steve. Ale to było lepsze rozwiązanie, ponieważ sed -i umożliwia edycję w miejscu.

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

Jedynym sposobem mogę myśleć to zrobić w awk bez użycia pętli jest użycie gsub na $0 łączyć sąsiadujące 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 
}' 

jeden dwa trzy cztery pięć sześć

jeden dwa cztery pięć sześć

trzy

0

dobrze, jeśli celem jest, aby usunąć dodatkowe ograniczniki następnie można użyć " tr "w systemie Linux. Przykład:

$ echo "1,2 ,,, 5" | tr -s „”

1,2,5

Powiązane problemy