Włamałem się do wielu skryptów powłoki i czasami najprostsze rzeczy mnie zaskakują. Dzisiaj natknąłem się na skrypt, który szeroko wykorzystywał :
wbudowane bash (dwukropek).
Documenation wydaje się dość proste:
: (a colon) : [arguments]
Nie rób nic poza rozszerzaniem argumentów i przeprowadzaniem przekierowań. Status powrotu wynosi zero.
Jednak wcześniej widziałem to tylko w demonstracjach ekspansji powłoki. Przypadek użycia w skrypcie, na który natknąłem się, w dużym stopniu wykorzystywał tę strukturę:
if [ -f ${file} ]; then
grep some_string ${file} >> otherfile || :
grep other_string ${file} >> otherfile || :
fi
W rzeczywistości były setki grepów, ale są one po prostu takie same. Nie ma żadnych przekierowań wejścia / wyjścia poza prostą strukturą powyżej. Żadne zwracane wartości nie są sprawdzane później w skrypcie.
Czytam to jako bezużyteczną konstrukcję, która mówi „albo nic nie rób”. Jaki cel może mieć zakończenie tych grepów „lub nic nie robić”? W jakim przypadku ten konstrukt spowodowałby inny wynik niż zwyczajne pominięcie || :
wszystkich przypadków?
źródło
:
jako alternatywy dlatrue
. Być możeerrexit
jest ustawiony, a autor nie dba o status wyjścia niektórych poleceń.Odpowiedzi:
Wygląda na
:
to, że zamiast twojego skryptu używane są literytrue
. Jeśligrep
nie znajdzie dopasowania w pliku, zwróci niezerowy kod wyjścia; jak jw013 wspomina w komentarzu, jeślierrexit
jest ustawiony, prawdopodobnie-e
w linii shebang, skrypt zakończy działanie, jeśli którykolwiek z nichgrep
nie znajdzie pasującego elementu. Najwyraźniej nie tego chciał autor, więc dodał,|| :
aby status wyjścia tego konkretnego polecenia złożonego zawsze wynosił zero, jak w przypadku bardziej powszechnego (z mojego doświadczenia)|| true
/|| /bin/true
.źródło
true
zamiast tego, ale cel semantyczny jest znacznie wyraźniejszytrue
.:
jest bardziej odpowiedni, gdy pożądany jest wyraźny NOP.:
zamiast tego,true
ponieważ:
jest tobash
wbudowany, gdzie jaktrue
zwykle skompilowany plik binarny z większym narzutem. zwykle używam,true
ponieważ kod jest bardziej czytelny (podobnie wolę używaćsource
zamiast.
).:
Wbudowane jest także przydatny z „przypisać wartości domyślne” ekspansji powłoki bash, gdzie ekspansja jest często wykorzystywane wyłącznie na efekt uboczny, a wartość rozszerzony jest wyrzucane:źródło
Mogę wymyślić dwa miejsca, z których korzystałem
:
w przeszłości.To jest pętla na zawsze.
Włącz funkcję odgałęzienia, aby uzyskać prawidłowy przepływ sterowania na najwyższym poziomie.
Jedno użycie, które widziałem w dawnych czasach: Zamiast
#!/bin/sh
(lub cokolwiek) linii, zobaczyłbyś:
linię. Niektóre starsze jądra Real Unix lub powłoki Real Unix użyłyby tego w znaczeniu „Jestem skryptem powłoki, uruchomiłem”. Jak pamiętam, było to właśnie wtedy, gdy csh robił inwazje jako wspólna interaktywna powłoka.źródło
:
jest bardzo dziwne. odkryłem, że rzeczywiście powoduje to uruchomienie skryptush
. gdzie tak jak podczas uruchamiania skryptu bez shebang ... próbuje uruchomić skrypt z jakąkolwiek uruchomioną powłoką (więc jeślibash
go uruchomisz , spróbuje uruchomić go takbash
, jakbyścsh
to zrobiłcsh
).:
Wbudowaną był już w Thompson skorupy - to udokumentowane na Unix V6 w roku 1975. W Thompson skorupkach,:
wskazany etykietęgoto
polecenia. Jeśli nigdy nie próbowałeś zadzwonićgoto
na linię zaczynającą się od:
, ta linia była faktycznie komentarzem.Bourne shell , przodek muszli Bourne'a / POSIX, jakie znamy, nigdy nie miał
goto
o tym nie wiem, ale zachowane:
jako no-op polecenie (to był już obecny w Unix V7 ).źródło
Wykopałem stare odniesienie: „The UNIX Programming Environment” (c) 1984 autorstwa Kernighana i Pike'a.
Strona 147 (Programowanie powłoki) mówi:
źródło
true
jest teraz także powłoką wbudowaną w wiele systemów.Wydaje mi się, że pamiętam, że wczesne wersje powłoki nie miały składni komentarzy. Linia zaczynająca się od
:
(która prawdopodobnie byłaby rzeczywistym plikiem wykonywalnym, podobnym do/bin/true
) byłaby najlepszą alternatywą.Oto strona podręcznika dla starożytnej powłoki Thompsona (bez relacji); nie ma wzmianki o żadnej składni komentarza.
źródło
:
było w rzeczywistości wskaźnikiem etykiety dlagoto
polecenia, w jakiejś starożytnej powłoce (nie wiem która). Etykieta: something
rzeczywiście mogłaby zostać użyta jako komentarz, gdyby nie było pasującegogoto
. Praktyka utknęła nawet pogoto
zniknięciu.„:” jest przydatne do debugowania.
Działa normalnie, funkcja debugowania nigdy nie jest wykonywana, więc po prostu przesuń się o krok dalej (zmienne i symbole wieloznaczne są rozwijane). Jeśli wymagane jest bardziej szczegółowe debugowanie, usuń noop ze zmiennej, a funkcja debugowania zostanie wywołana z dowolnymi wymaganymi argumentami.
Innym przydatnym zastosowaniem jest komentarz blokowy, który jest brakującą cechą składni powłoki.
źródło