Nie można przenośnie umieścić więcej niż jednego argumentu w #!
wierszu . Oznacza to tylko pełną ścieżkę i jeden argument (np. #!/bin/sed -f
Lub #!/usr/bin/sed -f
) lub #!/usr/bin/env
brak argumentu dla tłumacza.
Obejściem, które pozwala uzyskać przenośny skrypt, jest użycie #!/bin/sh
i otoki powłoki, które przekazują skrypt sed jako argument wiersza poleceń. Zauważ, że nie jest to sankcjonowane przez POSIX (skrypty składające się z wielu instrukcji muszą być napisane z osobnym -e
argumentem dla każdej instrukcji przenośności), ale działa z wieloma implementacjami.
#!/bin/sh
exec sed '
s/a/b/
' "$@"
W przypadku długiego skryptu wygodniejsze może być użycie heredoc. Zaletą heredoc jest to, że nie musisz cytować pojedynczych cudzysłowów, jeśli takie istnieją. Główną wadą jest to, że skrypt jest zasilany standardowym wejściem, co ma dwie irytujące konsekwencje. Niektóre wersje sed wymagają -f /dev/stdin
zamiast tego -f -
, co stanowi problem w zakresie przenośności. Co gorsza, skrypt nie może działać jako filtr, ponieważ standardowym wejściem jest skrypt i nie mogą to być dane.
#!/bin/sh
exec sed -f - -- "$@" <<'EOF'
s/a/b/
EOF
Minusem heredoka można zaradzić poprzez przydatne użycie cat
. Ponieważ powoduje to ponowne umieszczenie całego skryptu w wierszu poleceń, nie jest on zgodny z POSIX, ale w dużej mierze jest przenośny w praktyce.
#!/bin/sh
exec sed "$(cat <<'EOF')" -- "$@"
s/a/b/
EOF
Innym obejściem jest napisanie skryptu, który można przeanalizować zarówno przez sh, jak i przez sed. Jest przenośny, dość wydajny, tylko trochę brzydki.
#! /bin/sh
b ()
{
x
}
i\
f true; then exec sed -f "$0" "$@"; fi
: ()
# sed script starts here
s/a/b/
Objaśnienia:
- Pod sh: zdefiniuj funkcję o nazwie
b
; zawartość nie ma znaczenia, o ile funkcja jest poprawnie sformatowana pod względem składniowym (w szczególności nie można mieć pustej funkcji). Następnie, jeśli jest to prawda (tj. Zawsze), uruchom sed
skrypt.
- Pod sedem: przejdź do
()
etykiety, a następnie dobrze sformułowany tekst. Następnie i
polecenie, które nie działa, ponieważ zawsze jest pomijane. Na koniec ()
etykieta, po której następuje przydatna część skryptu.
- Testowane pod GNU sed, BusyBox i OpenBSD. (Możesz uzyskać coś prostszego w GNU sed, ale OpenBSD sed jest wybredny w kwestii części, które pomija.)