O ile mi wiadomo, [[
jest ulepszoną wersją [
, ale jestem zdezorientowany, gdy widzę [[
jako słowo kluczowe i [
jest wyświetlany jako wbudowany.
[root@server ~]# type [
[ is a shell builtin
[root@server ~]# type [[
[[ is a shell keyword
TLDP mówi
Wbudowany może być synonimem polecenia systemowego o tej samej nazwie, ale Bash ponownie go implementuje wewnętrznie. Na przykład polecenie echa Bash nie jest takie samo jak / bin / echo, chociaż ich zachowanie jest prawie identyczne.
i
Słowo kluczowe to słowo zastrzeżone, token lub operator. Słowa kluczowe mają specjalne znaczenie dla powłoki i faktycznie są elementami składni składni powłoki. Jako przykłady, dla, while, do i! są słowami kluczowymi. Podobnie jak wbudowane słowo kluczowe jest na stałe zakodowane w Bash, ale w przeciwieństwie do wbudowanego słowa kluczowego samo w sobie nie jest poleceniem, ale podjednostką konstrukcji polecenia. [2]
Nie powinno to zrobić zarówno [
i [[
słowa kluczowego? Czy coś tu mi brakuje? Również ten link ponownie potwierdza, że zarówno [
i [[
powinien należeć do tego samego rodzaju.
źródło
if "[" $x -eq 3 ]
działa zgodnie z oczekiwaniami (bo Bash wygląda polecenia o nazwie[
, a ta istnieje), aleif "[[" $x -eq 3 ]]
nie nie działa (bo znowu Bash wyszukuje polecenie odpowiedniej nazwy, ale tam nie ma[[
Komenda)./usr/bin/echo
, ale to nie znaczy, że to nie jest wbudowane .Odpowiedzi:
Różnica między
[
i[[
jest dość fundamentalna.[
to polecenie. Jego argumenty są przetwarzane tak samo, jak inne argumenty poleceń. Rozważ na przykład:Powłoka rozszerzy się
$name
i wykona zarówno podział słów, jak i generowanie nazw plików, tak jak w przypadku każdego innego polecenia.Na przykład poniższe działanie zakończy się niepowodzeniem:
Aby ta funkcja działała poprawnie, konieczne są cytaty:
[[
jest słowem kluczowym powłoki, a jego argumenty są przetwarzane zgodnie ze specjalnymi regułami. Rozważ na przykład:Powłoka wzrośnie
$name
, ale w przeciwieństwie do jakiegokolwiek innego polecenia, wykona ani podział na słowa ani nazwy pliku pokolenia na wynik. Na przykład następujące działania się powiodą pomimo spacji osadzonych wname
:Podsumowanie
[
jest poleceniem i podlega tym samym regułom, co wszystkie inne polecenia wykonywane przez powłokę.Ponieważ
[[
jest słowem kluczowym, a nie poleceniem, powłoka traktuje go specjalnie i działa na bardzo różnych zasadach.źródło
man bash
. Zobacz w szczególności sekcje zatytułowane „PROSTE ROZSZERZENIE POLECEŃ” i „WYKONANIE POLECEŃ”. Oprócz[[
inne bash słowa kluczowe obejmująif
,then
,while
i „case”. Nie ma ogólnych zasad dla słów kluczowych: każde słowo kluczowe jest szczególnym przypadkiem.man bash
zawiera szczegóły dla każdego.W V7 Unix - gdzie debiutowała powłoka Bourne'a -
[
był nazywanytest
i istniał tylko jako/bin/test
. Więc kod, który napiszesz dzisiaj jako:napisałbyś zamiast tego jako
Ta druga notacja wciąż istnieje i uważam, że jest bardziej jasne o tym, co się dzieje: wywołujesz komendę o nazwie call
test
, która ocenia jej argumenty i zwraca kod statusu wyjścia, któryif
używa do podjęcia decyzji, co dalej. To polecenie może być wbudowane w powłokę lub może być programem zewnętrznym.¹[
jako alternatywa dlatest
późniejszych. ² Może to być wbudowany synonimtest
, ale jest również zapewniony tak jak/bin/[
w nowoczesnych systemach dla powłok, które nie mają go jako wbudowanego.[
itest
może być zaimplementowany przy użyciu tego samego kodu. Jest to przypadek/bin/[
, a/bin/test
na OS X, gdzie są to twarde linki do tego samego executable.³ W rezultacie realizacja całkowicie ignoruje końcowego znaku]
: to nie wymaga go, jeśli nazwać to jak/bin/[
, a nie narzekać jeśli zrobić dostarczyć go do/bin/test
.⁴Żadna z tych historii nie ma wpływu
[[
, ponieważ nigdy nie istniał pierwotny program o nazwie[[
. Istnieje wyłącznie w tych powłokach, które implementują go jako rozszerzenie powłoki POSIX .Część rozróżnienia między „wbudowanym” a „słowem kluczowym” wynika z tej historii. Odzwierciedla to także fakt, że reguły składniowe dla parsowania
[[
wyrażeń są różne, jak wskazano w odpowiedzi John1024.Przypisy:
Patrząc na to w ten sposób, wyjaśnia się, dlaczego należy wstawiać spacje
[
w skryptach powłoki, w przeciwieństwie do sposobu, w jaki nawiasy i nawiasy działają w większości innych języków programowania. Jeśli parser poleceń powłoki jest dozwolonyif["$x"...
, będzie również musiał zezwolićiftest"$x"...
Stało się to około 1980 roku.
/bin/[
Nie istnieje w mojej kopii Ancient Unix V7 z 1979 roku, ani nieman test
dokumentuje tego jako aliasu. W analogicznym wpisu strony człowiek mam w kopii pre-release z systemu III podręcznika z 1980 roku, to jest na liście.ls -i /bin/[ /bin/test
Ale nie licz na to zachowanie. Wbudowana wersja Bash
[
wymaga zamknięcia]
, a jego wbudowanatest
implementacja będzie narzekać, jeśli to zrobisz .Rozróżnienie poleceń wbudowanych i zewnętrznych może mieć również znaczenie z innego powodu: obie implementacje mogą zachowywać się inaczej. Dotyczy to
echo
wielu systemów. Ponieważ istnieje tylko jedna implementacja, słowo kluczowe nie wymaga takiego rozróżnienia.źródło
builtin
ikeyword
rozróżnienie między[
i[[
kiedy oba zapewniają tę samą funkcjonalność (z wyjątkiem faktu, że[[
ma więcej funkcji niż[
)?[[
jako słowo kluczowe pozwala bashowi robić rzeczy, które nie są możliwe[
- na przykład cytowanie nie jest konieczne dużo czasu, ponieważ powłoka jest świadoma, że jest zmienną. Innymi słowy, przetwarzanie wiersza poleceń ma wpływ na użycie słowa kluczowego, ale nie na użycie wbudowanego - dzieje się to znacznie później.[
wbudowane, ale kod jest komentowany.cd
jest wbudowany, ale niczego nie przesłania (cd
nie można go zaimplementować jako programu zewnętrznego).[[
słowa kluczowego pozwala powłoce na użycie specjalnych reguł parsowania dla swoich argumentów. Tak więc, niestety, moje głosowanie idzie do John1024.[
było pierwotnie tylko zewnętrzną komendą, inną nazwą dla/bin/test
. Jednak kilka poleceń, takich jak[
iecho
, jest używanych tak często w skryptach powłoki, że implementatorzy powłoki postanowili skopiować kod bezpośrednio do samej powłoki, zamiast musieć uruchamiać inny proces za każdym razem, gdy są używane. To zmieniło te polecenia w „wbudowane”, chociaż nadal można wywoływać program zewnętrzny pełną ścieżką.[[
przyszedł znacznie później. Mimo że wbudowane funkcje są implementowane wewnętrznie w powłoce, są one przetwarzane podobnie jak polecenia zewnętrzne. Jak wyjaśniono w odpowiedzi John1024, oznacza to, że zmienne nienotowane otrzymają na nich podział słów, a tokeny lubią>
i<
są przetwarzane jako przekierowanie We / Wy. To sprawiło, że pisanie skomplikowanych wyrażeń porównawczych było niewygodne.[[
został utworzony jako składnia powłoki, aby można go było parsować ideosynchronicznie.[[
Zmienne wewnątrz nie dzielą się na słowa<
i>
mogą być używane jako operatory porównania,=
mogą zachowywać się inaczej w zależności od tego, czy następny parametr jest cytowany czy nie, itp. Są to wszystkie udogodnienia, które są[[
łatwiejsze w użyciu niż tradycyjne[
polecenie / wbudowane.Nie mogli po prostu przekodować
[
takiej składni, ponieważ byłaby to niezgodna zmiana w milionach skryptów. Korzystając z nowej[[
składni, która wcześniej nie istniała, mogli całkowicie przebudować sposób, w jaki jest ona używana w sposób kompatybilny w górę.Jest to podobne do ewolucji, która zaowocowała
$((...))
składnią wyrażeń arytmetycznych, która w większości zastąpiła tradycyjneexpr
polecenie.źródło
Nowsza
[[
wbash
to optymalizacja z[
.Klasyk
[
ma jedną dużą wadę, ponieważ jest często używany do trywialnej operacji: za każdym razem odradza się nowy proces:(Tworzy nową przestrzeń adresową tylko do porównywania
0
i1
! Za każdym razem!)Myślę, że głównym punktem dodania
[[
było sprawienie, aby ocena wyrażenia wewnątrz[
nie była procesem dodatkowym. Ale jak[
działa nie można zmienić - byłoby utworzyć wiele nieporozumień i problemów. Tak więc optymalizacja została zaimplementowana pod nową nazwą, w bardziej wydajny sposób, mianowicie z wbudowanym poleceniem powłoki.Stał się słowem kluczowym w składni powłoki jako efekt uboczny.
W tym momencie
[
był używany pierwszy, był to właściwy sposób, aby to zrobić za pomocą zewnętrznego procesu.źródło
[
pierwotnie było to polecenie zewnętrzne, zostało dodane jako wbudowane w powłokę dość wcześnie, prawdopodobnie do czasu wydania Unix System III i zdecydowanie przed wydaniem Unix System V. Tak więc „dodatkowy proces” nie był problemem od wieków. Jednak składnia pozostała niezmieniona - traktowano ją jak polecenie zewnętrzne.[
obydwoma - to oznacza pewne zmiany ...