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.

Czy to stwierdzenie jest prawdziwe czy fałszywe?


Zobacz Dlaczego cofanie cudzysłowów w skrypcie powłoki nie pomogło mi cdw katalogu, na przykład dlaczego $(...)notacja jest łatwiejsza w użyciu niż zagnieżdżone cudzysłowy.
Jonathan Leffler


1
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 przestarzałe.

Nieaktualny stan może również oznaczać, że funkcja zostanie usunięta w przyszłości.

- Wikipedia

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.

  • BashFAQ # 082 - Dlaczego $ (...) jest lepszy niż `...` (backticks)?

    fragment

    `...`jest starszą składnią wymaganą tylko przez najstarszą z nieobsługiwanych powłok bourne-shell. Istnieje kilka powodów, aby zawsze preferować $(...)składnię:

    ...

  • Bash Hackers Wiki - Przestarzała i przestarzała składnia

    fragment

    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)? .

  • Standardowe uzasadnienie POSIX

    fragment

    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.


26
Według większości znaczeń przestarzałych , ja (i ty) powiedziałbym, że backticks 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:

    echo "x is $(sed ... <<<"$y")"

    zamiast:

    echo "x is `sed ... <<<\"$y\"`"

    lub pisząc coś takiego:

    IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`

    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.

    Kilka innych przykładów:

    echo `echo `ls``      # INCORRECT
    echo `echo \`ls\``    # CORRECT
    echo $(echo $(ls))    # CORRECT
  • 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.

Źródło: Dlaczego $(...)preferowane `...`(backticks)? w BashFAQ

Zobacz też:

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.