Zrozumienie backtick (`)

35

Wypróbowuję polecenie

$ b=5; echo `$b`;
-bash: 5: command not found

ale nie drukuje 5 tak, jak powinno. Czego tu brakuje?

Co oznacza `(backquote / backtick) w poleceniach? zdaje się mówić, że `ocenia polecenia wewnątrz i zamienia je na dane wyjściowe.

coolcric
źródło
8
Zauważ, że backtyki nie są zalecane, ponieważ stracisz możliwość wykonywania zagnieżdżonych zamian wykonania. Insetad, $ (somecommand) jest preferowany. Imho poprawia czytelność.
Tommy
6
@Tommy, Nie, backticks można zagnieżdżać, ale staje się on ucieczką z koszmaru, szczególnie w przypadku podwójnego cytowania.
Stéphane Chazelas

Odpowiedzi:

52

Tekst między odwrotnymi wierszami jest wykonywany i zastępowany przez dane wyjściowe polecenia (minus końcowe znaki nowego wiersza i uwaga, że ​​zachowanie powłoki różni się, gdy w wyniku są znaki NUL). Nazywa się to podstawieniem polecenia, ponieważ jest ono zastąpione wynikiem działania polecenia. Więc jeśli chcesz wydrukować 5, nie możesz używać odwrotnych znaków, możesz używać znaków cudzysłowu, jak echo "$b"lub po prostu upuścić dowolną ofertę i użyć echo $b.

Jak widać, ponieważ $bzawiera 5, podczas korzystania z backticks bashpróbuje uruchomić polecenie, 5a ponieważ nie ma takiego polecenia, nie powiedzie się komunikat o błędzie.

Aby zrozumieć, jak działają backticks, spróbuj uruchomić to:

$ A=`cat /etc/passwd | head -n1`
$ echo "$A"

cat /etc/passwd |head -n1powinien wydrukować pierwszy wiersz /etc/passwdpliku. Ale ponieważ używamy backticków, nie drukuje tego na konsoli. Zamiast tego jest przechowywany w Azmiennej. Możesz to powtórzyć $A. Zauważ, że bardziej wydajnym sposobem drukowania pierwszego wiersza jest użycie polecenia, head -n1 /etc/passwdale chciałem zwrócić uwagę, że wyrażenie w backticks nie musi być proste.

Więc jeśli pierwsza linia / etc / passwd to root:x:0:0:root:/root:/bin/bash, pierwsza komenda zostanie dynamicznie zastąpiona przez bash do A="root:x:0:0:root:/root:/bin/bash".

Zauważ, że ta składnia dotyczy powłoki Bourne'a. Cytowanie i ucieczka szybko stają się koszmarem, zwłaszcza gdy zaczniesz je zagnieżdżać. Ksh wprowadził $(...)alternatywę, która jest teraz znormalizowana ( POSIX ) i obsługiwana przez wszystkie powłoki (nawet powłokę Bourne'a z Uniksa v9). Dlatego powinieneś używać $(...)zamiast tego, chyba że musisz być przenośny do bardzo starych pocisków Bourne'a.

Zauważ też, że wyniki `...`i $(...)podlegają dzieleniu słów i generowaniu nazw plików, podobnie jak rozwijanie zmiennych (tylko w Zsh, tylko dzielenie słów), więc ogólnie trzeba by je cytować w kontekście listowym.

Krzysztof Adamski
źródło
1
Cześć @Krzysztof, to jest pomocne! „ponieważ $ b zawiera 5, bash próbuje uruchomić komendę 5” właśnie tego szukałem
coolcric
you can use quotation marks, like echo "$b"=> czy „” robi coś specjalnego? Wygląda na to, echo $bże zadziała równie dobrze.
Tootsie Rolls
@Anita: W ogólnych znakach cudzysłowu robi pewne specjalne rzeczy (zmienia sposób traktowania znaków specjalnych - zwłaszcza białych spacji), ale w tym przypadku można je upuścić bez większych problemów. Wynika to z faktu, że nie są używane żadne znaki specjalne, a echopolecenie nie dba o liczbę argumentów, które dostaje, więc jeśli bma w nim trochę spacji, otrzyma wiele argumentów i nadal je wydrukuje. Nie może tak być w przypadku innych poleceń (szczególnie gdy zmienna nie jest ustawiona), więc zwykle otaczam zmienne cudzysłowami.
Krzysztof Adamski
byłoby miło, gdyby (POSIX)był link do faktycznego standardu.
erikbwork
1
@ erikb85: Ta notatka nie została dodana przeze mnie, ale edytowałem ją z linkiem zgodnie z sugestią :)
Krzysztof Adamski
11

Backtick wykonuje dokładnie to, co mówisz. Ustawiłeś zmienną na liczbę całkowitą. Kiedy umieścisz tę zmienną w backticksie, bash spróbuje wykonać ją jako polecenie. Ponieważ nie jest to polecenie, pojawia się wyświetlony błąd.

To, co chcesz zrobić, to po prostu:

$ b=5; echo $b

Aby lepiej zrozumieć backticks, porównaj z:

$ b=5; a=`echo $b`; echo $a
  5
terdon
źródło
8

Idąc krok po kroku, twoja linia powinna to wyjaśnić.

$ b=5; echo `$b`;
  1. ustawia zmienną bna 5
  2. ocenia $b(efektywnie działa 5)
  3. echoJest to wynik powyższej oceny.

Tak więc, oczekiwany wynik jest oczekiwany. Oceniasz zawartość zmiennej, a nie rzeczywiste polecenie, o którym myślałeś, że jesteś. Wszystko, co umieścisz w backtickach, jest oceniane (uruchamiane) w nowej (pod) powłoce.

gertvdijk
źródło
cześć @gertvdijk, dzięki za twój post! Myślałem, że `zwraca wszystko, co pozostało po ocenie jego zawartości. Pomyślałem więc, że „$ b” zwróciłoby 5 za echo, aby je wydrukować
coolcric