Czy backticks (tj. `Cmd`) w powłokach * sh są przestarzałe?
118
Wiele razy widziałem ten komentarz na Unixie i Linuksie, a także na innych stronach używających frazowania „backticks are przestarzały”, w odniesieniu do powłok takich jak Bash i Zsh.
Co najmniej jeden system uniksowy, AIX, udokumentował, że backty są przestarzałe . „Chociaż ksh akceptuje składnię tylnego cytatu, jest ona uważana za przestarzałą w X / Open Portability Guide Issue 4 i standardach POSIX. Standardy te zalecają, aby aplikacje przenośne korzystały ze składni $ (polecenie)”. ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.osdevice/…
Christopher
Mam wyraźną różnicę w „GNU bash, wersja 3.2.57 (1) -release (x86_64-apple-darwin14)” na Macu 10.10: matchingLines=$( grep -n '\$-PARAMETER' ... | ... )działa, matchingLines= backtick the same stuff backticknie działa - wydaje się, że traci odwrotny ukośnik w odwrotnym ukośniku. (To nie jest mój skrypt ...)
den
Odpowiedzi:
126
Istnieją dwa różne znaczenia słowa „przestarzałe”.
być przestarzałe: (głównie funkcja oprogramowania) może być użyteczne, ale uważane za przestarzałe i najlepiej unikane, zazwyczaj z powodu zastąpienia.
—Nowy słownik Oxford American
Zgodnie z tą definicją backticks są przestarzałe.
Nieaktualny stan może również oznaczać, że funkcja zostanie usunięta w przyszłości.
Według tej definicji backtyki nie są przestarzałe.
Nadal obsługiwane:
Powołując się na specyfikację otwartej grupy w językach poleceń powłoki , w szczególności w sekcji „2.6.3 Zastępowanie poleceń”, można zauważyć, że obie formy zastępowania poleceń, backticks ( `..cmd..`) lub dolara ( $(..cmd..)) są nadal obsługiwane, o ile idzie specyfikacja.
fragment
Podstawienie polecenia pozwala na zastąpienie wyjścia polecenia zamiast samej nazwy polecenia. Podstawienie polecenia następuje, gdy polecenie jest dołączone w następujący sposób:
$(command)
or (backquoted version):`command`
Powłoka rozszerza podstawianie poleceń, wykonując polecenie w środowisku podpowłoki (patrz Środowisko wykonywania powłoki) i zastępując podstawienie polecenia (tekst polecenia wraz z załącznikami $()lub cudzysłowami) standardowym wyjściem polecenia, usuwając sekwencje jednego lub więcej <newline> znaków na końcu podstawienia. Osadzone <newline> znaki przed końcem danych wyjściowych nie zostaną usunięte; można je jednak traktować jako ograniczniki pól i eliminować podczas dzielenia pól, w zależności od wartości IFS i obowiązującego cytowania. Jeśli dane wyjściowe zawierają bajty zerowe, zachowanie nie jest określone.
W ramach stylów zastępowania poleceń w cudzysłowie <lashlash> zachowuje swoje dosłowne znaczenie, z wyjątkiem następujących po nim znaków: „$”, „ \`” lub <backlash> . Poszukiwanie pasującego cudzysłowu musi być spełnione przez pierwszy niecytowany nie ocalony cytat; podczas tego wyszukiwania, jeśli w komentarzu powłoki napotkany zostanie nieoznaczony znak zapytania, pojawi się dokument tutaj, osadzone polecenie w $(command)formularzu lub ciąg cytowany, wyniki niezdefiniowane. Ciąg pojedynczego lub podwójnego cudzysłowu, który zaczyna się, ale nie kończy, w `...`sekwencji „ ” daje niezdefiniowane wyniki.
W $(command)formularzu wszystkie znaki następujące po otwartym nawiasie do pasującego nawiasu zamykającego stanowią polecenie. Do polecenia można użyć dowolnego poprawnego skryptu powłoki, z wyjątkiem skryptu składającego się wyłącznie z przekierowań, który daje nieokreślone wyniki.
Dlaczego więc wszyscy mówią, że backticks są przestarzałe?
Ponieważ większość przypadków użycia powinna wykorzystywać formę dolara amerykańskiego zamiast odwrotnych. (Nieaktualne w pierwszym sensie powyżej.) Wiele najbardziej renomowanych witryn (w tym U&L) również często o tym informuje, więc to dobra rada. Porady tej nie należy mylić z jakimś nieistniejącym planem usunięcia wsparcia dla backticksa z powłok.
`...`jest starszą składnią wymaganą tylko przez najstarszą z nieobsługiwanych powłok bourne-shell. Istnieje kilka powodów, aby zawsze preferować $(...)składnię:
Jest to starsza kompatybilna z Bourne forma zastępowania poleceń . Zarówno składnia, jak `COMMANDS`i $(COMMANDS)składnia są określone przez POSIX, ale ta druga jest bardzo preferowana, chociaż ta pierwsza jest niestety nadal bardzo rozpowszechniona w skryptach. Zastępowania poleceń w nowym stylu są szeroko implementowane przez każdą nowoczesną powłokę (i niektóre). Jedynym powodem korzystania z backticków jest kompatybilność z prawdziwą powłoką Bourne'a (jak Heirloom). Zastępowania poleceń za pomocą backticka wymagają specjalnego ucieczki po zagnieżdżeniu, a przykłady znalezione w środowisku naturalnym są niepoprawnie cytowane częściej niż nie. Zobacz:
Dlaczego $ (...) jest lepszy niż `...` (backticks)? .
Z powodu tych niespójnych zachowań nie zaleca się stosowania poprzednio cytowanych odmian podstawiania poleceń dla nowych aplikacji, które zagnieżdżają podstawienia poleceń lub próbują osadzić złożone skrypty.
UWAGA: Ten trzeci fragment (powyżej) pokazuje kilka sytuacji, w których backty po prostu nie działają, ale działa na nich metoda nowszych dolarów, zaczynając od następującego akapitu:
Ponadto składnia cytowana wstecz ma historyczne ograniczenia dotyczące zawartości wbudowanego polecenia. Podczas gdy nowszy formularz „$ ()” może przetwarzać dowolny prawidłowy skrypt osadzony, formularz z cudzysłowem nie obsługuje niektórych prawidłowych skryptów zawierających cudzysłowy.
Jeśli będziesz dalej czytać tę sekcję, awarie zostaną podświetlone, pokazując, jak nie powiodłyby się przy użyciu backticksa, ale pracuj przy użyciu nowszej notacji parens.
Wnioski
Dlatego lepiej jest używać parenów zamiast dolarowych, ale tak naprawdę nie używasz czegoś, co było technicznie „przestarzałe”, jak w „to przestanie działać całkowicie w pewnym zaplanowanym punkcie”.
Po przeczytaniu tego wszystkiego powinieneś zabrać ze sobą to, że gorąco zachęcasz do korzystania z parens dolara, chyba że potrzebujesz konkretnej kompatybilności z prawdziwą oryginalną powłoką Bourne'a inną niż POSIX.
Według większości znaczeń przestarzałych , ja (i ty) powiedziałbym, że backticks są przestarzałe. To głównie pytanie terminologiczne.
Stéphane Chazelas
4
@StephaneChazelas - Zgoda! Nadal będę mówił ppl, że są przestarzałe, ale backsticksy nie zostały oficjalnie „przestarzałe” w tym sensie, że w najbliższej przyszłości zostaną aktywnie usunięte z bazy kodu dowolnej powłoki. Przynajmniej nie jestem tego świadomy.
slm
3
Moja interpretacja jest taka, że cudzysłowy są obsługiwane wyłącznie dlatego, że są zbyt głęboko zakorzenione w istniejącym kodzie, aby formalnie przestać być używane. Nigdy nie słyszałem argumentów za dalszym użyciem ich w nowym kodzie.
chepner
3
@slm Tak, chyba to dostałeś - zostałem odciągnięty i nie zauważyłem. Nie ma prawie żadnego powodu, aby używać tych rzeczy, z wyjątkiem tego, że może być tylko trochę czystszy podczas nakładania warstw na podpowłoki, więc $( cmd `cmd`)jest tylko trochę mniej bałagan niż $( cmd $(cmd))- jest łatwiejszy do odczytania. Po prostu zawsze uważałem przestarzałą funkcję w oprogramowaniu za oficjalnie oznaczoną do usunięcia przez upstream - i nigdy o tym nie słyszałem. Nie obchodzi mnie to - nie kochajcie grobu.
mikeserv
3
Możesz chcieć dodać następujący cytat ze standardowego uzasadnienia POSIX : Z powodu tych niespójnych zachowań, zastępowanie cytowanych odmian zastępowania poleceń nie jest zalecane dla nowych aplikacji, które zagnieżdżają podstawienia poleceń lub próbują osadzić złożone skrypty. Chociaż nie jest to formalne zaniechanie, ponieważ sekcja uzasadnienia ma charakter informacyjny, a nie normatywny, sugeruje, że należy unikać ciągłego stosowania backkicks.
jw013
15
Nie jest przestarzałe, ale backticks ( `...`) jest starszą składnią wymaganą tylko przez najstarszą z nieobsługiwanych powłok bourne-powłok i $(...)jest POSIX i bardziej preferowany z kilku powodów:
Backslashes ( \) w backticksach są obsługiwane w nieoczywisty sposób:
$ echo "`echo \\a`""$(echo \\a)"
a \a
$ echo "`echo \\\\a`""$(echo \\\\a)"
\a \\a
# Note that this is true for *single quotes* too!
$ foo=`echo '\\'`; bar=$(echo '\\'); echo "foo is $foo, bar is $bar"
foo is \, bar is \\
Zagnieżdżanie cytatów w środku $()jest znacznie wygodniejsze:
ponieważ $()używa zupełnie nowego kontekstu do cytowania
który nie jest przenośny, ponieważ pociski Bourne'a i Korna wymagałyby tych odwrotnych ukośników, podczas gdy Bash i dash nie.
Składnia do zagnieżdżania podstawień poleceń jest łatwiejsza:
x=$(grep "$(dirname "$path")" file)
niż:
x=`grep "\`dirname \"$path\"\`" file`
ponieważ $()wymusza zupełnie nowy kontekst cytowania, więc każde zastąpienie polecenia jest chronione i może być traktowane samodzielnie, bez specjalnej troski o cytowanie i ucieczkę. Podczas korzystania z backticków staje się on coraz brzydszy po dwóch i więcej poziomach.
Rozwiązuje problem niespójnego zachowania podczas używania cudzysłowów:
echo '\$x' wyjścia \$x
echo `echo '\$x'` wyjścia $x
echo $(echo '\$x') wyjścia \$x
Składnia backticks ma historyczne ograniczenia dotyczące zawartości wbudowanego polecenia i nie może obsłużyć niektórych prawidłowych skryptów zawierających cudzysłowy, podczas gdy nowsza $()forma może przetwarzać dowolny prawidłowy osadzony skrypt.
Na przykład te skądinąd prawidłowe skrypty osadzone nie działają w lewej kolumnie, ale działają na prawym IEEE :
echo ` echo $(
cat <<\eof cat <<\eof
a here-doc with ` a here-doc with )
eof eof
` )
echo ` echo $(
echo abc # a comment with ` echo abc # a comment with )` )
echo ` echo $(
echo '`' echo ')'` )
W związku z tym preferowaną metodą powinna być składnia $zastępowania poleceń z prefiksem , ponieważ jest wizualnie przejrzysta z czystą składnią (poprawia czytelność dla ludzi i maszyn), jest zagnieżdżalna i intuicyjna, jej wewnętrzna analiza jest oddzielna, a także bardziej spójna (z wszystkie inne rozszerzenia, które są parsowane w obrębie podwójnych cudzysłowów), w których jedynymi wyjątkami są odwrotne `znaki, a znak można łatwo zakamuflować w sąsiedztwie, "co czyni go jeszcze trudniejszym do odczytania, szczególnie w przypadku małych lub niezwykłych czcionek.
cd
w katalogu, na przykład dlaczego$(...)
notacja jest łatwiejsza w użyciu niż zagnieżdżone cudzysłowy.matchingLines=$( grep -n '\$-PARAMETER' ... | ... )
działa,matchingLines= backtick the same stuff backtick
nie działa - wydaje się, że traci odwrotny ukośnik w odwrotnym ukośniku. (To nie jest mój skrypt ...)Odpowiedzi:
Istnieją dwa różne znaczenia słowa „przestarzałe”.
Zgodnie z tą definicją backticks są przestarzałe.
Według tej definicji backtyki nie są przestarzałe.
Nadal obsługiwane:
Powołując się na specyfikację otwartej grupy w językach poleceń powłoki , w szczególności w sekcji „2.6.3 Zastępowanie poleceń”, można zauważyć, że obie formy zastępowania poleceń, backticks (
`..cmd..`
) lub dolara ($(..cmd..)
) są nadal obsługiwane, o ile idzie specyfikacja.fragment
Dlaczego więc wszyscy mówią, że backticks są przestarzałe?
Ponieważ większość przypadków użycia powinna wykorzystywać formę dolara amerykańskiego zamiast odwrotnych. (Nieaktualne w pierwszym sensie powyżej.) Wiele najbardziej renomowanych witryn (w tym U&L) również często o tym informuje, więc to dobra rada. Porady tej nie należy mylić z jakimś nieistniejącym planem usunięcia wsparcia dla backticksa z powłok.
BashFAQ # 082 - Dlaczego $ (...) jest lepszy niż `...` (backticks)?
fragment
Bash Hackers Wiki - Przestarzała i przestarzała składnia
fragment
Standardowe uzasadnienie POSIX
fragment
UWAGA: Ten trzeci fragment (powyżej) pokazuje kilka sytuacji, w których backty po prostu nie działają, ale działa na nich metoda nowszych dolarów, zaczynając od następującego akapitu:
Jeśli będziesz dalej czytać tę sekcję, awarie zostaną podświetlone, pokazując, jak nie powiodłyby się przy użyciu backticksa, ale pracuj przy użyciu nowszej notacji parens.
Wnioski
Dlatego lepiej jest używać parenów zamiast dolarowych, ale tak naprawdę nie używasz czegoś, co było technicznie „przestarzałe”, jak w „to przestanie działać całkowicie w pewnym zaplanowanym punkcie”.
Po przeczytaniu tego wszystkiego powinieneś zabrać ze sobą to, że gorąco zachęcasz do korzystania z parens dolara, chyba że potrzebujesz konkretnej kompatybilności z prawdziwą oryginalną powłoką Bourne'a inną niż POSIX.
źródło
$( cmd `cmd`)
jest tylko trochę mniej bałagan niż$( cmd $(cmd))
- jest łatwiejszy do odczytania. Po prostu zawsze uważałem przestarzałą funkcję w oprogramowaniu za oficjalnie oznaczoną do usunięcia przez upstream - i nigdy o tym nie słyszałem. Nie obchodzi mnie to - nie kochajcie grobu.Nie jest przestarzałe, ale backticks (
`...`
) jest starszą składnią wymaganą tylko przez najstarszą z nieobsługiwanych powłok bourne-powłok i$(...)
jest POSIX i bardziej preferowany z kilku powodów:Backslashes (
\
) w backticksach są obsługiwane w nieoczywisty sposób:Zagnieżdżanie cytatów w środku
$()
jest znacznie wygodniejsze:zamiast:
lub pisząc coś takiego:
ponieważ
$()
używa zupełnie nowego kontekstu do cytowaniaktóry nie jest przenośny, ponieważ pociski Bourne'a i Korna wymagałyby tych odwrotnych ukośników, podczas gdy Bash i dash nie.
Składnia do zagnieżdżania podstawień poleceń jest łatwiejsza:
niż:
ponieważ
$()
wymusza zupełnie nowy kontekst cytowania, więc każde zastąpienie polecenia jest chronione i może być traktowane samodzielnie, bez specjalnej troski o cytowanie i ucieczkę. Podczas korzystania z backticków staje się on coraz brzydszy po dwóch i więcej poziomach.Kilka innych przykładów:
Rozwiązuje problem niespójnego zachowania podczas używania cudzysłowów:
echo '\$x'
wyjścia\$x
echo `echo '\$x'`
wyjścia$x
echo $(echo '\$x')
wyjścia\$x
Składnia backticks ma historyczne ograniczenia dotyczące zawartości wbudowanego polecenia i nie może obsłużyć niektórych prawidłowych skryptów zawierających cudzysłowy, podczas gdy nowsza
$()
forma może przetwarzać dowolny prawidłowy osadzony skrypt.Na przykład te skądinąd prawidłowe skrypty osadzone nie działają w lewej kolumnie, ale działają na prawym IEEE :
W związku z tym preferowaną metodą powinna być składnia
$
zastępowania poleceń z prefiksem , ponieważ jest wizualnie przejrzysta z czystą składnią (poprawia czytelność dla ludzi i maszyn), jest zagnieżdżalna i intuicyjna, jej wewnętrzna analiza jest oddzielna, a także bardziej spójna (z wszystkie inne rozszerzenia, które są parsowane w obrębie podwójnych cudzysłowów), w których jedynymi wyjątkami są odwrotne`
znaki, a znak można łatwo zakamuflować w sąsiedztwie,"
co czyni go jeszcze trudniejszym do odczytania, szczególnie w przypadku małych lub niezwykłych czcionek.Źródło: Dlaczego
$(...)
preferowane`...`
(backticks)? w BashFAQZobacz też:
źródło