Czy są 2 sposoby na ustawienie vk awar za pomocą wiersza poleceń?

10

Zauważyłem awkprzykład O'Reilly'ego (1997), który przypisał zmienną awk, ustawiając ją w wierszu poleceń po tekście programu. Działa, ale nie mogę znaleźć tej składni w man / info awk . Czy właśnie tęskniłem; czy to jest deprecjonowane ...? Jedyną składnią, jaką widziałem w instrukcji, jest -vopcja.

awk '/home/{print foo, bar}' foo="cat" bar="dog" /proc/$$/cmdline

Wynik: cat dog

Peter.O
źródło

Odpowiedzi:

11

Tak naprawdę jest w POSIX awk(link do POSIX 2008, wierzę, że poprzednie wersje też go miały). -vjest opisany w sekcji Opcje , a drugi to sekcja Operandy .

Istnieje różnica między -vprzekazywaniem zadań na końcu z nazwami plików:

  • Z -v:

Wniosek zapewnia, aby argument przypisania był w tej samej formie, co argument operacji przypisania. Określone przypisanie zmiennych powinno nastąpić przed uruchomieniem programu awk, w tym działań związanych ze wzorcami BEGIN (jeśli istnieją). Można określić wiele wystąpień tej opcji.

  • Pomieszane z nazwami plików:

[...] Każde takie przypisanie zmiennej powinno nastąpić tuż przed przetworzeniem następującego pliku , jeśli taki istnieje. W związku z tym przypisanie przed pierwszym argumentem pliku zostanie wykonane po akcji BEGIN (jeśli istnieje), a przypisanie po ostatnim argumencie pliku nastąpi przed działaniami END (jeśli występuje). Jeśli nie ma argumentów pliku, przypisania należy wykonać przed przetworzeniem standardowego wejścia.

Przykład:

$ cat input 
hello
hello
$ awk -v var=one 'BEGIN{print var} /hello/{print var} END{print var}' \
    var=two input var=three input var=four
one
two
two
three
three
four
Mata
źródło
Łał! Dodaje to kilka interesujących punktów kontrolnych ... na pewno się przyda. Dzięki ...
Peter.O
1
Moje początkowe „Wow!” nadal się utrzymuje, ale został nieco zahartowany przez dalsze spojrzenie na odpowiedź Arcege ... Przetestowałem go z prawdziwym plikiem o nazwie "var = trzy" ... awkdawałem pierwszeństwo temu, że jest zmiennym przypisaniem ... Ma to poważny skutek , tj. We wszystkich przypadkach, gdy nazwa pliku ma ten formularz, zostanie zignorowana, a zmienna zostanie ustawiona ... Wydaje się, że jedynym sposobem uniknięcia tego konfliktu jest upewnienie się, że nazwy plików dla bieżącego katalogu roboczego muszą być zawsze poprzedzone z ich względną ścieżką:./var=three
Peter.O
@ Peter.O, tak, to także jeden z powodów, dla których wprowadzono -vskładnię. Powinieneś pomyśleć o -vskładni jako preferowanym sposobie wykonywania zadań w przyszłości.
dubiousjim
@ Peter.O, doskonała uwaga na temat „gotcha”, jeśli nazwa pliku jest prawidłowym przypisaniem zmiennej. Jeśli używasz zmiennej powłoki zawierającej nazwę pliku i przekazujesz ją jako argument awk, możesz użyć następującego haczyka:[ "$myfile" == "${myfile#/}" ] && myfile="./$myfile"
Wildcard
4

Jest to stary styl zewnętrznego ustawiania zmiennych awk. To było niejednoznaczne (co jeśli masz nazwę pliku foo=cat), więc późniejsze wersje dodały -vopcję. Prawdopodobnie powinno działać dla kompatybilności wstecznej, ale nie można tego zagwarantować. I jak powiedziałem, -vopcja jest nowsza, więc nie wszystkie wersje awkmogą ją obsługiwać.

Arcege
źródło
Twój komentarz na temat możliwości zderzenia nazwy pliku jest dobry ... Przetestowałem go i jest to z pewnością problem. Trochę więcej napisałem na ten temat w komentarzu do odpowiedzi Mat. Thansk za podkreślenie tego problemu (+1)
Peter.O
2
W rzeczywistości, jak wyjaśniono w [Mat s answer](http://unix.stackexchange.com/a/34258/9537), -v`, przypisanie argumentów różni się, gdy zaczynają obowiązywać. -vJest także w POSIX-ie i powinien być obecny we wszystkich awkimplementacjach oprócz najstarszych . Korzystanie ./lub upewniając się, że nazwa pliku zawiera znak zakaz identyfikator jest prawdopodobnie najbardziej niezawodnym sposobem na dwuznaczności.
jw013,