Mam ten skrypt powłoki zapisany w pliku: podstawia ciąg znaków.
#!/bin/sh
html_file=$1
echo "html_file = $html_file"
substr=.pdf
pdf_file="${html_file/.html/.pdf}"
echo "pdf_file = $pdf_file"
Jeśli wkleję go do wiersza poleceń, działa dobrze:
$ html_file="/home/max/for_pauld/test_no_base64.html"
echo "html_file = $html_file"
substr=.pdf
pdf_file="${html_file/.html/.pdf}"
echo "pdf_file = $pdf_file"
daje
html_file = /home/max/for_pauld/test_no_base64.html
pdf_file = /home/max/for_pauld/test_no_base64.pdf
To jest wynik z echa powyżej - działa zgodnie z przeznaczeniem.
Ale kiedy wywołuję skrypt, z
$ saucer "/home/max/for_pauld/test_no_base64.html"
Otrzymuję ten wynik:
html_file = /home/max/for_pauld/test_no_base64.html
/home/max/bin/saucer: 5: /home/max/bin/saucer: Bad substitution
Czy mój skrypt używa innej wersji bash czy coś takiego? Czy muszę zmienić linię shebang?
sh
ibash
. Przeczytam o tym. Jeśli zechcesz zamienić komentarz w odpowiedź, oznaczę go poprawnie.#!/usr/bin/env bash
jako shebang i używaj odpowiednio zdefiniowanych podstawień, jak chcesz, ale z zastrzeżeniami dotyczącymi przenośności. I przeczytaj: unix.stackexchange.com/a/48787/27616Odpowiedzi:
Co to jest sh
sh
(lub Shell Command Language) to język programowania opisany przez standard POSIX . Posiada wiele wdrożeń (ksh88
,dash
...).bash
można również uznać za wdrożeniesh
(patrz poniżej).Ponieważ
sh
specyfikacja, a nie implementacja,/bin/sh
jest dowiązaniem symbolicznym (lub dowiązaniem twardym) do rzeczywistej implementacji w większości systemów POSIX.Co to jest bash
bash
zaczęło się jakosh
implementacja kompatybilna (chociaż wyprzedza standard POSIX o kilka lat), ale z czasem zyskała wiele rozszerzeń. Wiele z tych rozszerzeń może zmienić zachowanie prawidłowych skryptów powłoki POSIX, więc samo w sobiebash
nie jest prawidłową powłoką POSIX. Jest to raczej dialekt języka powłoki POSIX.bash
obsługuje--posix
przełącznik, co czyni go bardziej zgodnym z POSIX. Próbuje również naśladować POSIX, jeśli zostanie wywołany jakosh
.sh = bash?
Przez długi czas
/bin/sh
wskazywał/bin/bash
na większość systemów GNU / Linux. W rezultacie prawie bezpiecznie stało się ignorowanie różnicy między nimi. Ale to zaczęło się ostatnio zmieniać.Niektóre popularne przykłady systemów, na które
/bin/sh
nie wskazuje/bin/bash
(a niektóre z nich/bin/bash
mogą nawet nie istnieć) to:sh
dodash
których domyślnie prowadzi dowiązanie symboliczne ;initramfs
. Wykorzystujeash
implementację powłoki.pdksh
, potomek powłoki Korn. FreeBSDsh
jest potomkiem oryginalnej powłoki UNIX Bourne. Solaris ma swój własny,sh
który przez długi czas nie był zgodny z POSIX; darmowa implementacja jest dostępna z projektu Heirloom .Jak możesz dowiedzieć się, na co
/bin/sh
wskazuje twój system?Komplikacja polega na tym, że
/bin/sh
może to być dowiązanie symboliczne lub dowiązanie twarde. Jeśli jest to łącze symboliczne, przenośnym sposobem jego rozwiązania jest:Jeśli jest to twardy link, spróbuj
W rzeczywistości
-L
flaga obejmuje zarówno dowiązania symboliczne, jak i dowiązania twarde, ale wadą tej metody jest to, że nie jest przenośna - POSIX nie wymagafind
obsługi-samefile
opcji, chociaż zarówno GNU find, jak i FreeBSD ją obsługują.Linia Shebang
Ostatecznie to Ty decydujesz, którego użyć, pisząc wiersz «shebang».
Na przykład
użyje
sh
(i cokolwiek innego, co wskaże),użyje,
/bin/bash
jeśli jest dostępny (i zakończy się niepowodzeniem z komunikatem o błędzie, jeśli nie jest). Oczywiście możesz również określić inną implementację, npKtórego użyć
W przypadku moich własnych skryptów wolę
sh
z następujących powodów:bash
, trzeba je miećsh
Istnieją również zalety korzystania z niego
bash
. Jego funkcje sprawiają, że programowanie jest wygodniejsze i podobne do programowania w innych współczesnych językach programowania. Należą do nich takie zmienne lokalne i tablice o zasięgu. Zwykłysh
to bardzo minimalistyczny język programowania.źródło
/bin/sh
rzeczywiście jest dowiązaniem symbolicznym/bin/dash
.Dodając do doskonałej odpowiedzi z @ Hunter.S. Thompson, chciałbym zauważyć, że nieprzenośną częścią skryptu jest
Jest
${variable/search/replace}
to rozszerzenie GNU. Ale możesz tego łatwo uniknąć dzięki czystemu POSIX:Po Hunterze jest to lepsze rozwiązanie niż zmiana shebang na
#! /bin/bash
źródło