Dystrybucja skryptu: Czy powinienem używać / bin / gawk lub / usr / bin / gawk dla shebang?

12

Czy zwykle gawk znajduje się w / bin lub / usr / bin? Poszedłbym z tym, #!/usr/bin/env gawkale wtedy nie mogę używać argumentów. Teraz używam #!/bin/gawk -f. Skrypt jest bardzo długi i zawiera wiele pojedynczych cudzysłowów i współpracuje ze stdin.

Podręcznik GNU Awk zawiera sekcję 1.1.4 Wykonywalne programy awk, w których używa #! / Bin / awk w swoim przykładzie, ale mówi dalej:

Zauważ, że w wielu systemach awkmożna znaleźć /usr/binzamiast w /bin. Zastrzeżenie Emptor.

Co robi większość ludzi? Przeczytałem, że sed jest podobno ustandaryzowany w / bin, podczas gdy perl jest podobno ustandaryzowany w / usr / bin (ta sama strona co link sed, ale nie pozwalają mi na utworzenie trzeciego linku do tego postu). Co z awk / gawk? Czy ktoś wie, który jest bardziej powszechny lub popularny?

użytkownik2672807
źródło
Dlaczego używacie -f? Nie /bin/gawkwystarczy Także, to może być istotne.
terdon

Odpowiedzi:

7

Shebang nie miał być tak elastyczny . Mogą istnieć przypadki, w których drugi parametr działa , myślę, że FreeBSD jest jednym z nich.

gawk i większość programów narzędziowych, które są dostarczane z systemem operacyjnym, powinny być dostępne /usr/bin/.

W starszych czasach systemu UNIX powszechne było /usr/montowanie w systemie plików NFS lub na niektórych tańszych nośnikach w celu zaoszczędzenia miejsca na dysku lokalnym i kosztów na stację roboczą. /bin/miał mieć wszystko, co potrzebne do uruchomienia w trybie pojedynczego użytkownika . Ponieważ /usr/nie został zamontowany na niezawodnym nośniku, /bin/zawierał wystarczającą liczbę narzędzi, aby uczynić go wystarczająco przyjaznym do ogólnej administracji i rozwiązywania problemów.

Zostało to odziedziczone początkowo w Linuksie, ale ponieważ przestrzeń dyskowa nie stanowi już problemu, aw większości przypadków /usr/znajduje się w głównym systemie plików, obecnym trendem jest przenoszenie wszystkiego /usr/bin(przynajmniej w świecie Linuksa). Dlatego oczekuje się, że znajdzie się tam większość narzędzi zainstalowanych przez dystrybucję. Nawet najbardziej podstawowe narzędzia, takie jak cp, rm, lsitp (no, jeszcze nie).

Jeśli chodzi o wybór shebang. Tradycyjnie jest to coś, co administratorzy lub użytkownicy muszą edytować w zależności od środowiska. Dla wszystkich programista wie, w systemach innych ludzi, interpreter może być gdziekolwiek w systemie plików (np /usr/local/bin, /opt/gawk-4.0.1/bin). Prawidłowo spakowane skrypty (rpm, deb itp.) Pochodzą albo z zależności od pakietu dystrybucyjnego (tzn. Interpreter ma znaną lokalizację), albo ze skryptu konfiguracyjnego, który konfiguruje właściwy hashbang podczas instalacji.

forcefsck
źródło
14

Jeśli nie musisz przekazywać argumentów do polecenia, #!/usr/bin/env gawkjest to dobry sposób, jednak wiele jąder (w tym Linux) akceptuje tylko jeden argument w programach shebang.

W przeciwnym razie możesz utworzyć program poliglotyczny , który jest zarówno opakowaniem powłoki, jak i skryptem awk. Oto jeden na awk.

#!/bin/sh
true + /; exec gawk -f "$0"; exit; / {}
# awk script starts here

Analiza powłoki:

  • true + /;- polecenie true(które nic nie robi) z dwoma obojętnymi argumentami +i /.
  • Wezwanie do gawk. Może to być dowolny fragment powłoki, który nie zawiera znaków nowej linii i gdzie są pisane ukośniki \/(powłoka nie ma nic przeciwko, oprócz cytatów wewnętrznych).
    Wywołanie używa execdo zastąpienia powłoki gawk zamiast wykonywania gawk jako podprocesu.
  • exit;- wyjdź z powłoki, na wypadek gdyby gawk nie został znaleziony. Wszystko, co później zostanie zignorowane, z wyjątkiem tego, że powinna być poprawna składnia powłoki na wypadek, gdyby powłoka spróbowała parsować całą linię przed jej uruchomieniem.

Awk parsowanie:

  • Bit między ukośnikami jest wyrażeniem regularnym.
  • true + /REGEX/- stan. truejest niezdefiniowaną zmienną, więc jej wartość liczbowa wynosi 0, ale nie ma znaczenia.
  • {} - Jeśli wspomniany warunek się utrzymuje, nie rób nic.
Gilles „SO- przestań być zły”
źródło
5

Proponowane rozwiązanie Gillesa jest rzeczywiście bardzo dobrym podejściem (w końcu ma reputację głosować w swoim poście :)).

W każdym razie, o ile rozumiem execpolecenie, powoduje, że exitzaraz po nim jest niepotrzebne, w rzeczywistości nieosiągalne, ponieważ proces powłoki jest zastępowany przez awk.

Ponadto, aby umożliwić awkskryptowi dostęp do jego parametrów wywołania, sugerowałbym pewne zmiany w proponowanym rozwiązaniu:

#!/bin/sh
true + /; exec -a "$0" gawk -f "$0" -- "$@"; / {}
# awk script starts here

-a "$0"Pozwala skrypt mieć dostęp do swojej nazwy wywołania, inaczej będzie zawsze dostać awklub gawkpodczas uzyskiwania dostępu do ARGV[0]zmiennej. Podobnie, "$@"skrypt pozwala na dostęp do pozostałych parametrów w ARGV[1...N]tablicy, a --poprzedni pozwala skryptowi na otrzymywanie -<something>argumentów bez interpretacji ich przez gawk.

Jedną rzeczą do zapamiętania / rozważenia jest dodanie exit(0);instrukcji na końcu BEGIN { ... }bloku awkprogramu skryptowego, w przeciwnym razie awkzagrozi wszystkim parametrom przekazanym do skryptu jako pliki wejściowe. (Pamiętaj, że w ogóle nie ma to nic wspólnego z exitinstrukcją, którą usunęliśmy z true + ...wiersza, była to nieosiągalna instrukcja powłoki, podczas gdy to sugerowane wyjście znajduje się w kodzie awk).

Marcelo
źródło
To exit(0)było bardzo przydatne! Ponadto, dla użytkowników systemu Macos, zapoznaj się z tą treścią: dobry przenośny awk shebang nie jest łatwy do znalezienia.
Seamus