Chciałbym wykonać skrypt gawk z --re-interval
użyciem shebang. „Naiwne” podejście
#!/usr/bin/gawk --re-interval -f
... awk script goes here
nie działa, ponieważ gawk jest wywoływany z pierwszym argumentem "--re-interval -f"
(niepodzielonym na białe znaki), którego nie rozumie. Czy istnieje obejście tego problemu?
Oczywiście możesz albo nie wywołać gawk bezpośrednio, ale zawinąć go w skrypt powłoki, który rozdziela pierwszy argument, lub stworzyć skrypt powłoki, który następnie wywoła gawk i umieści skrypt w innym pliku, ale zastanawiałem się, czy jest jakiś sposób do zrobienia to w jednym pliku.
Zachowanie linii shebang różni się w zależności od systemu - przynajmniej w Cygwin nie dzieli argumentów białymi spacjami. Po prostu obchodzi mnie, jak to zrobić w systemie, który zachowuje się w ten sposób; skrypt nie jest przeznaczony do przenoszenia.
--re-interval
nie jest już potrzebny (patrz [ gnu.org/software/gawk/manual/… ).Odpowiedzi:
Wydaje się, że działa to dla mnie z (g) awk.
Zwróć uwagę na
#!
przebiegi/bin/sh
, więc ten skrypt jest najpierw interpretowany jako skrypt powłoki.Na początku po prostu próbowałem
"exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"
, ale awk traktował to jako polecenie i bezwarunkowo drukował każdy wiersz wejścia. Dlatego stawiamarbitrary_long_name==0
- ma cały czas zawodzić. Mógłbyś go zastąpić jakimś bełkotem. Zasadniczo szukałem fałszywego warunku w awk, który nie wpłynąłby negatywnie na skrypt powłoki.W skrypcie powłoki
arbitrary_long_name==0
definiuje zmienną o nazwiearbitrary_long_name
i ustawia ją na=0
.źródło
bash
, czy będzie działać z jakimkolwiek POSIXsh
? I nie używamawk
często, więc nie jestem pewien, czy moja sztuczka na drugiej linii jest dobrym sposobem na wymuszenieawk
ignorowania linii.arbitrary_long_name
nie koliduje ze zmienną używaną w prawdziwym programie awk, nie widzę żadnego problemu. Czy jest coś, czego mi brakuje?#!/bin/sh -
zamiast,#!/bin/sh
aby chronić skrypt przed możliwym niewłaściwym zachowaniem się w niebezpieczny sposób, jeśli zostanie wywołany z argumentem zerowym, który ma-
jako pierwszy znak. Może się to zdarzyć przypadkowo w językach programowania, takich jak C, gdzie łatwo jest przypadkowo zepsuć, zapominając o przekazaniu wywoływanej nazwy programu jako części tablicy argumentów doexecve
i podobnych funkcji, a jeśli ludzie zwykle zapominają się przed tym chronić, może również w końcu jest ostatnim krokiem w złośliwie możliwej do wykorzystania luce, która umożliwia atakującemu uzyskanie interaktywnej powłoki.Linia shebang nigdy nie została określona jako część specyfikacji POSIX, SUS, LSB ani żadnej innej specyfikacji. AFAIK, nie zostało to nawet odpowiednio udokumentowane.
Istnieje przybliżony konsensus co do tego, co robi: weź wszystko między
!
a a\n
iexec
it. Założenie jest takie, że wszystko pomiędzy!
i a\n
jest pełną, absolutną ścieżką do tłumacza. Nie ma zgody co do tego, co się stanie, jeśli zawiera spacje.Na szczęście 1. i 4. wydają się wymarły, ale 3. jest dość rozpowszechnione, więc po prostu nie można polegać na możliwości przekazania więcej niż jednego argumentu.
A ponieważ lokalizacja poleceń nie jest również wymieniony w POSIX lub SUS, zazwyczaj zużywają że jednym argumentem przepuszczając wykonywalnego nazwę na
env
tak, to możemy określić lokalizacji wykonywalnego; na przykład:[Oczywiście, nadal zakłada to określoną ścieżkę
env
, ale jest tylko kilka systemów, w których żyje/bin
, więc jest to ogólnie bezpieczne. Lokalizacjaenv
jest o wiele bardziej ustandaryzowana niż lokalizacjagawk
lub nawet gorzej, jakpython
lubruby
lubspidermonkey
.]Co oznacza, że nie można rzeczywiście używają żadnych argumentów w ogóle .
źródło
-S
przełącznik, który pomaga tutaj, ale nie ma go w moim Linuksieenv
i podejrzewam, że nie jest również dostępny na gygwin. @hstoerr, inni użytkownicy w innych sytuacjach mogą później czytać twoje pytania, więc generalnie preferowane są przenośne odpowiedzi, nawet jeśli teraz nie potrzebujesz przenośności.#!/bin/sh
i/usr/bin/env gawk --re-interval -f my-script.awk
. Czy to jest poprawne?#!
samo w sobie nie jest przenośne. Na przykład system Windows w ogóle nie rozpoznaje tej konwencji „natywnie”. W Uniksie tradycyjnie potrzebny jest jeden argument, aby móc to zrobić#!/usr/bin/awk -f
.#!/usr/bin/env ruby
lub lajki.Chociaż nie do końca przenośny, zaczynając od coreutils 8.30 i zgodnie z jego dokumentacją będziesz mógł używać:
Więc biorąc pod uwagę:
dostaniesz:
a jeśli jesteś ciekawy
showargs
to:Oryginalna odpowiedź tutaj .
źródło
Natknąłem się na ten sam problem, bez widocznego rozwiązania ze względu na sposób, w jaki obsługiwane są białe znaki w shebang (przynajmniej w Linuksie).
Można jednak przekazać kilka opcji w shebang, tak długo jak są one krótkie opcje i mogą być łączone (drogę GNU).
Na przykład nie możesz tego mieć
ale możesz mieć
Oczywiście działa to tylko wtedy, gdy opcje mają krótkie odpowiedniki i nie pobierają żadnych argumentów.
źródło
Pod Cygwinem i Linuksem wszystko po ścieżce shebang jest analizowane do programu jako jeden argument.
Można to obejść, używając innego
awk
skryptu wewnątrz shebang:Spowoduje to wykonanie
{system("/usr/bin/gawk --re-interval -f " FILENAME); exit}
w awk.I to zostanie wykonane
/usr/bin/gawk --re-interval -f path/to/your/script.awk
w powłoce twojego systemu.źródło
Powyższa sztuczka z shebangiem powłoki jest bardziej przenośna niż
/usr/bin/env
.źródło
python
, ale to pytanie dotyczyawk
.W podręczniku do gawk (http://www.gnu.org/manual/gawk/gawk.html) na końcu sekcji 1.14 zauważ, że podczas uruchamiania gawk z linii shebang należy używać tylko jednego argumentu. Mówi, że system operacyjny potraktuje wszystko po ścieżce do gawk jako pojedynczy argument. Być może istnieje inny sposób określenia
--re-interval
opcji? Być może twój skrypt może odwoływać się do twojej powłoki w linii shebang, działaćgawk
jako polecenie i dołączyć tekst twojego skryptu jako „dokument tutaj”.źródło
gawk
, ale nadal możesz być w stanie przesłać coś potokiem przez stderr (to znaczy przekierować stdout na stderr przed potokowaniem do tego skryptu). Nigdy tego nie próbowałem, ale jeśli pierwszy proces nie emituje niczego na stderr, może to zadziałać. Możesz także utworzyć nazwany potok ( linuxjournal.com/content/using-named-pipes-fifos-bash ), jeśli chcesz się upewnić, że nic innego go nie używa.Dlaczego nie użyć
bash
igawk
siebie, aby pominąć shebang, przeczytać skrypt i przekazać go jako plik do drugiej instancjigawk [--with-whatever-number-of-params-you-need]
?(-the samo może oczywiście być również realizowana np
sed
albotail
, ale myślę, że istnieje jakiś rodzaj piękna w zależności tylko odbash
igawk
sobie;)źródło
Dla zabawy: istnieje następujące dość dziwne rozwiązanie, które przekierowuje stdin i program przez deskryptory plików 3 i 4. Możesz także utworzyć tymczasowy plik dla skryptu.
Jedna rzecz jest w tym denerwująca: powłoka wykonuje w skrypcie rozwinięcie zmiennych, więc musisz zacytować każdy $ (tak jak to zrobiono w drugiej linii skryptu) i prawdopodobnie więcej.
źródło
W przypadku rozwiązania przenośnego użyj
awk
zamiastgawk
wywoływać standardową powłokę BOURNE (/bin/sh
) za pomocą swojego shebang i wywołajawk
bezpośrednio, przekazując program w wierszu poleceń jako dokument tutaj zamiast przez stdin:Uwaga: brak
-f
argumentu doawk
. To pozostawiastdin
dostępneawk
do odczytania danych wejściowych. Zakładając, żegawk
zainstalowałeś i na swoimPATH
, daje to wszystko, co myślę, że próbowałeś zrobić z oryginalnym przykładem (zakładając, że chcesz, aby zawartość pliku była skryptem awk, a nie danymi wejściowymi, co myślę, że twoje podejście shebang potraktowałoby to jako ).źródło