Jaki jest cel polecenia, które nic nie robi, będąc niewiele więcej niż liderem komentarzy, ale w rzeczywistości jest wbudowaną powłoką samą w sobie?
Jest to wolniejsze niż wstawianie komentarza do skryptów o około 40% na wywołanie, co prawdopodobnie różni się znacznie w zależności od wielkości komentarza. Jedyne możliwe powody, dla których to widzę, to:
# poor man's delay function
for ((x=0;x<100000;++x)) ; do : ; done
# inserting comments into string of commands
command ; command ; : we need a comment in here for some reason ; command
# an alias for `true' (lazy programming)
while : ; do command ; done
Wydaje mi się, że tak naprawdę szukam historycznej aplikacji.
Odpowiedzi:
Historycznie , muszle Bourne nie miał
true
ifalse
jak wbudowanych komend.true
zamiast tego został po prostu alias do:
ifalse
do czegoś podobnegolet 0
.:
jest nieco lepszy niż wtrue
przypadku przenoszenia do starożytnych pocisków pochodzących z Bourne'a. Jako prosty przykład rozważmy brak!
operatora potoku i operatora||
listy (tak jak w przypadku niektórych starożytnych powłok Bourne'a). Pozostawia toelse
klauzulęif
instrukcji jako jedyny sposób na rozgałęzienie na podstawie statusu wyjścia:Ponieważ
if
wymaga niepustejthen
klauzuli, a komentarze nie liczą się jako niepuste,:
służy jako brak opcji.W dzisiejszych czasach (czyli: w nowoczesnym kontekście) zazwyczaj można użyć jednej
:
lubtrue
. Oba są określone przez POSIX, a niektóre sątrue
łatwiejsze do odczytania. Jest jednak jedna interesująca różnica::
jest to tak zwany POSIX specjalne wbudowane , podczas gdytrue
jest to normalne wbudowane .Specjalne wbudowane elementy muszą być wbudowane w powłokę; Zwykłe wbudowane są tylko „typowo” wbudowane, ale nie jest to ściśle gwarantowane. Zwykle nie powinno być zwykłego programu o nazwie
:
z funkcjątrue
PATH większości systemów.Prawdopodobnie najważniejszą różnicą jest to, że przy specjalnych wbudowanych dowolnych zmiennych ustawionych przez wbudowane - nawet w środowisku podczas prostej oceny polecenia - pozostaje po zakończeniu polecenia, jak pokazano tutaj za pomocą ksh93:
Zauważ, że Zsh ignoruje to wymaganie, podobnie jak GNU Bash, z wyjątkiem pracy w trybie kompatybilności z POSIX, ale wszystkie inne ważne powłoki „pochodnej sh POSIX” przestrzegają tego, włączając dash, ksh93 i mksh.
Kolejna różnica polega na tym, że regularne wbudowane elementy muszą być kompatybilne
exec
- zademonstrowane tutaj za pomocą Bash:POSIX również wyraźnie zauważa, że
:
może być szybszy niżtrue
, choć jest to oczywiście szczegół specyficzny dla implementacji.źródło
exec
?true
jest to zwykłe narzędzie wbudowane, ale nieexec
ma/bin/true
racji, że używa zamiast niego.: ${var?not initialized}
i in.:
jest to wbudowana funkcja specjalna i nie powinna mieć nazwanej funkcji. Ale czy nie jest najczęściej spotykanym przykładem:(){ :|: & };:
nazewnictwa bomby nazewniczej funkcji o nazwie:
?Używam go do łatwego włączania / wyłączania poleceń zmiennych:
A zatem
To sprawia, że skrypt jest czysty. Nie można tego zrobić za pomocą „#”.
Również,
jest jednym z najprostszych sposobów zagwarantowania, że „afile” istnieje, ale ma zerową długość.
źródło
>afile
jest jeszcze prostszy i osiąga ten sam efekt.vecho=":"
? Tylko dla czytelności?Przydatna aplikacja dla: jest, jeśli interesuje Cię tylko stosowanie rozszerzeń parametrów do ich skutków ubocznych, a nie przekazywanie ich wyników do polecenia. W takim przypadku używasz PE jako argumentu: albo false, w zależności od tego, czy chcesz mieć status wyjścia 0 czy 1. Przykładem może być
: "${var:=$1}"
. Ponieważ:
jest wbudowany, powinien być dość szybki.źródło
: $((a += 1))
(++
i--
operatory nie muszą być implementowane zgodnie z POSIX.). W bash, ksh i ewentualnych innych powłokach możesz także:((a += 1))
lub,((a++))
ale nie jest to określone przez POSIX.(())
jest określona jako funkcja opcjonalna. „Jeśli sekwencja znaków rozpoczynająca się od„ ((”zostanie przeanalizowana przez powłokę jako rozszerzenie arytmetyczne, jeśli poprzedzona przez„ $ ”, powłoki, które implementują rozszerzenie, według których„ ((wyrażenie)) ”jest oceniane jako wyrażenie arytmetyczne może traktować „((jako wprowadzenie jako obliczenie arytmetyczne zamiast polecenia grupowania.”:
może być również dla komentarza blokowego (podobnie jak / * * / w języku C). Na przykład, jeśli chcesz pominąć blok kodu w skrypcie, możesz to zrobić:źródło
\
uciec którykolwiek z separatorów dla tego samego efektu:: <<\SKIP
.Jeśli chcesz skrócić plik do zera bajtów, co jest przydatne do czyszczenia dzienników, spróbuj tego:
źródło
> file.log
jest prostszy i osiąga ten sam efekt.:>
jest bardziej przenośny. Niektóre powłoki (takie jak mojazsh
) automatycznie tworzą instancję kota w bieżącej powłoce i nasłuchują standardowego wejścia po otrzymaniu przekierowania bez polecenia. Zamiastcat /dev/null
,:
jest o wiele prostsze. Często takie zachowanie jest inne w interaktywnych powłokach niż w skryptach, ale jeśli napiszesz skrypt w sposób, który działa również interaktywnie, debugowanie metodą kopiuj-wklej jest znacznie łatwiejsze.: > file
różni siętrue > file
(oprócz liczby postaci i szczęśliwej twarzy) nowoczesną powłoką (zakładając:
itrue
są równie szybkie)?Jest podobny do
pass
Pythona.Jednym z zastosowań byłoby wykasowanie funkcji, dopóki nie zostanie napisana:
źródło
Dwa kolejne zastosowania niewymienione w innych odpowiedziach:
Logowanie
Weź ten przykładowy skrypt:
W pierwszym wierszu
set -x
powłoka wypisuje polecenie przed jego uruchomieniem. To całkiem przydatna konstrukcja. Minusem jest to, że zwykłyecho Log message
typ instrukcji drukuje teraz wiadomość dwukrotnie. Metoda jelita grubego omija to. Pamiętaj, że nadal będziesz musiał uciec od znaków specjalnych, tak jak byś to zrobiłecho
.Nazwy stanowisk Cron
Widziałem, że jest używany w zadaniach crona, takich jak to:
To zadanie crona, które uruchamia skrypt
/opt/backup.sh
codziennie o 10:45. Zaletą tej techniki jest to, że poprawia wygląd tematów wiadomości e-mail, gdy/opt/backup.sh
drukuje jakieś dane wyjściowe.źródło
set -x
wydrukowane polecenia (w tym coś podobnego: foobar
) przechodzą do stderr.Możesz użyć go w połączeniu z backticks (
``
) do wykonania polecenia bez wyświetlania jego wyniku, jak poniżej:Oczywiście możesz po prostu to zrobić
some_command > /dev/null
, ale:
-wersja jest nieco krótsza.Biorąc to pod uwagę, nie polecałbym tego robić, ponieważ po prostu wprowadzałoby to w błąd ludzi. To właśnie przyszło mi do głowy jako możliwy przypadek użycia.
źródło
Jest także przydatny w przypadku programów poliglotycznych:
To jest teraz zarówno plik wykonywalny skrypt powłoki i program JavaScript: co oznacza
./filename.js
,sh filename.js
inode filename.js
wszystkie prace.(Zdecydowanie trochę dziwne użycie, ale mimo to skuteczne.)
Niektóre wyjaśnienia, zgodnie z prośbą:
Skrypty powłoki są oceniane linia po linii; a
exec
polecenie po uruchomieniu kończy powłokę i zastępuje jej proces wynikową komendą. Oznacza to, że dla powłoki program wygląda następująco:Dopóki nie występuje rozwinięcie parametru ani aliasing w słowie, każde słowo w skrypcie powłoki można zawijać w cudzysłów bez zmiany jego znaczenia; oznacza to, że
':'
jest to równoważne:
(umieściliśmy to tutaj w cudzysłowie, aby uzyskać semantykę JavaScript opisaną poniżej)... i jak opisano powyżej, pierwsze polecenie w pierwszym wierszu to no-op (przekłada się na
: //
, lub jeśli wolisz zacytować słowa,.':' '//'
Zwróć uwagę, że//
nie ma tutaj specjalnego znaczenia, tak jak w JavaScript; to tylko bezsensowne słowo, które jest wyrzucane).Wreszcie drugie polecenie w pierwszym wierszu (po średniku) jest prawdziwym mięsem programu: jest to
exec
wywołanie, które zastępuje wywoływany skrypt powłoki , a proces Node.js jest wywoływany w celu oceny reszty skryptu.Tymczasem pierwsza linia w JavaScript analizuje jako literał-ciąg (
':'
), a następnie komentarz, który jest usuwany; tak więc do JavaScript program wygląda następująco:Ponieważ literał-ciąg jest sam w wierszu, jest to instrukcja no-op, a zatem jest usuwana z programu; oznacza to, że cała linia jest usuwana, pozostawiając tylko kod programu (w tym przykładzie
function(){ ... }
treść).źródło
: //;
i~function(){}
robić? Dziękuję:)
~function(){}
, jest to trochę bardziej skomplikowane. Jest tu kilka innych odpowiedzi, które go dotykają, chociaż żadne z nich tak naprawdę nie wyjaśnia tego z moją satysfakcją… jeśli żadne z tych pytań nie wyjaśni ci wystarczająco dobrze, możesz opublikować je jako pytanie tutaj, będę chętnie udzielimy szczegółowych odpowiedzi na nowe pytanie.node
. Więc część funkcji dotyczy javascript! Nie mam nic przeciwko jednemu operatorowi przed IIFE. Pomyślałem, że to też była bash i tak naprawdę nie zrozumiałem znaczenia twojego postu. Teraz czuję się dobrze, dziękuję za poświęcony czas na dodanie „podziału”!~{ No problem. (= }
Funkcje samo dokumentowania
Możesz także użyć
:
do osadzenia dokumentacji w funkcji.Załóżmy, że masz skrypt biblioteczny
mylib.sh
zapewniający różne funkcje. Możesz albo pobrać bibliotekę (. mylib.sh
) i wywołać funkcje bezpośrednio po niej (lib_function1 arg1 arg2
), albo uniknąć zaśmiecania przestrzeni nazw i wywołać bibliotekę argumentem funkcji (mylib.sh lib_function1 arg1 arg2
).Czy nie byłoby miło, gdybyś mógł także wpisać
mylib.sh --help
i uzyskać listę dostępnych funkcji i ich użycia, bez konieczności ręcznego utrzymywania listy funkcji w tekście pomocy?Kilka komentarzy na temat kodu:
declare -f
do wyliczenia wszystkich dostępnych funkcji, a następnie filtruje je przez sed, aby wyświetlać tylko funkcje z odpowiednim prefiksem.mylib.sh function1
i zostanie on przetłumaczony wewnętrznie nalib_function1
. To ćwiczenie pozostawiono czytelnikowi.$1
. Jednocześnie zaśmieci twoją przestrzeń nazw, jeśli pozyskasz bibliotekę. Jeśli ci się to nie podoba, możesz zmienić nazwę na coś podobnegolib_help
lub faktycznie sprawdzić argumenty--help
w głównym kodzie i ręcznie wywołać funkcję pomocy.źródło
Widziałem to użycie w skrypcie i pomyślałem, że to dobry zamiennik dla wywoływania basename w skrypcie.
... jest to zamiennik kodu:
basetool=$(basename $0)
źródło
basetool=${0##*/}