Wartości rozdzielane tabulatorami w awk

90

Jak wybrać pierwszą kolumnę z ciągu rozdzielanego tabulatorami?

# echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk -F'\t' '{print $1}'

Powyższe zwróci całą linię, a nie tylko „LOAD_SETTLED”, zgodnie z oczekiwaniami.

Aktualizacja:

Muszę zmienić trzecią kolumnę w wartościach rozdzielonych tabulatorami. Poniższe nie działa.

echo $line | awk 'BEGIN { -v var="$mycol_new" FS = "[ \t]+" } ; { print $1 $2 var $4 $5 $6 $7 $8 $9 }' >> /pdump/temp.txt

Działa to jednak zgodnie z oczekiwaniami, jeśli separatorem jest przecinek zamiast tabulatora.

echo $line | awk -v var="$mycol_new" -F'\t' '{print $1 "," $2 "," var "," $4 "," $5 "," $6 "," $7 "," $8 "," $9 "}' >> /pdump/temp.txt
shantanuo
źródło
4
awk 'BEGIN {FS = "[\ t] +"}; {print $ 1} '# to jest to, czego szukałem. Czy moja wyszukiwarka Google jest poprawna? :)
shantanuo
3
Dzięki temu komentarzowi odkryłem: awk 'BEGIN {FS="\t"}; {print $1,FS,$2,FS,$3}' myFile.txtwydrukować wartości rozdzielane tabulatorami z pierwszych trzech kolumn.
Wok
6
A może po prostuawk 'BEGIN {OFS="\t"}; {print $1,$2,$3}'
Josiah Yoder
3
Wsparcie -vdla GNU i BSD awk do ustawiania zmiennych. Używanie BEGIN {FS="\t"}w programie wbudowanym jest brzydkie , a każdy wkład open source, który próbujesz w ten sposób wnieść, prawdopodobnie spotka się z sprzeciwem. Rób to tylko wtedy, gdy piszesz plik programu . Odradza się również używanie -Fzamiast, -v FS=ponieważ ten ostatni wyjaśnia, że ​​tylko FSjest ustawiany, a nie OFS. Zamieszanie w tym ostatnim punkcie spowodowało przede wszystkim ten post. Dlatego ważny jest „dobry styl”.
Bruno Bronosky
1
Proszę, nikt nigdy nie powinien robić tego, co pokazał @Wok. W swoim wyniku nie wyliczasz separatorów pól [wejściowych]. Separator pola wyjściowego określa się za pomocą OFSzmiennej.
Bruno Bronosky

Odpowiedzi:

141

Musisz ustawić OFSzmienną (separator pól wyjściowych) na kartę:

echo "$line" | 
awk -v var="$mycol_new" -F $'\t' 'BEGIN {OFS = FS} {$3 = var; print}'

(upewnij się, że cytujesz $linezmienną w instrukcji echo)

glenn jackman
źródło
6
Jaki jest cel znaku $ w $ '\ t'?
Amr Mostafa
10
Odpowiadając na moje własne pytanie z przewodnika Advanced Bash Scripting Guide : Konstrukcja rozwijająca ciąg znaków w cudzysłowie $ '...' to mechanizm, który wykorzystuje wartości ósemkowe lub szesnastkowe ze zmianą znaczenia ... np. Quote = $ '\ 042'.
Amr Mostafa
5
@AmrMostafa, szkoda, że prowadzący ma mylące wyjaśnienia prowadzącej do myślenia, że ty nie $w $'\t'nie jest potrzebne. Wiki Grega jest lepsza: „Spośród nich $'...'jest najbardziej powszechna i zachowuje się jak pojedyncze cudzysłowy, z wyjątkiem tego, że kombinacje ze znakami ucieczki odwrotnym ukośnikiem są interpretowane zgodnie ze standardem ANSI C”.
Cristian Ciupitu,
9
Z perspektywy czasu $'\t'nie jest to konieczne. awk rozumie, że ciąg "\t"jest znakiem tabulacji
glenn jackman
5
Współtwórcy Open Source, błagam, nie przesyłajcie takich rzeczy awk -F $'\t' 'BEGIN {OFS = FS} …'. Tak powinno być awk -v FS='\t' -v OFS='\t' '…'. Może się to wydawać pedantyczne, ale brak konsekwencji zwiększa szanse, że późniejszy współpracownik wprowadzi błąd, ponieważ źle zrozumie Twój kod.
Bruno Bronosky
21

Upewnij się, że to naprawdę tabulatura! W bashu możesz wstawić kartę za pomocąC-v TAB

$ echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk -F$'\t' '{print $1}'
LOAD_SETTLED
Mahmoud Abdelkader
źródło
9

Używam zmiennych FSi OFSdo manipulowania plikami stref BIND, które są rozdzielane tabulatorami. Oto jeden z moich skryptów https://gist.github.com/RichardBronosky/abe1652c2d5c78c35b92ad02bdf0d0af#file-dns_update-sh-L36-L39

Jej mięso to:

awk -v FS='\t' -v OFS='\t' \
    -v record_type=$record_type \
    -v hostname=$hostname \
    -v ip_address=$ip_address '
$1==hostname && $3==record_type {$4=ip_address}
{print}
' $zone_file > $temp

Jest to czysty i łatwy do odczytania sposób, aby to zrobić.

Bruno Bronosky
źródło
5
echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk -v var="test" 'BEGIN { FS = "[ \t]+" } ; { print $1 "\t" var "\t" $3 }'
shantanuo
źródło
0

Czy to nie powinno działać?

echo "LOAD_SETTLED    LOAD_INIT       2011-01-13 03:50:01" | awk '{print $1}'
asadz
źródło