Ocena ciągu w skrypcie powłoki

8

Śledzę ten przewodnik skryptowania powłoki bash:

W sekcji Porównania numeryczne przytacza przykład:

anny > num=`wc -l work.txt`

anny > echo $num
201

anny > if [ "$num" -gt "150" ]
More input> then echo ; echo "you've worked hard enough for today."
More input> echo ; fi

Wydaje się, że tak się dzieje powyżej: przechowujemy ciąg poleceń w zmiennej bash, a następnie wywołujemy echo zmiennej. Wydaje się, że tak się dzieje, że łańcuch jest analizowany i wykonywana jest komenda wc i zwraca liczbę linii do terminala sterującego.

Ok, więc uruchamiam mój terminal w Ubuntu 12.04 i próbuję czegoś podobnego:

$ touch sample.txt && echo "Hello World" > sample.txt
$ cat sample.txt
Hello World
$ num='wc -l sample.txt'
echo $num
wc -l sample.txt

Poczekaj chwilkę, która nie oceniła ciągu i zwróciła liczbę wierszy. To tylko powtórzyło ciąg z powrotem do terminala. Dlaczego otrzymałem różne wyniki?

JohnMerlino
źródło
Zauważ, że num nigdy nie jest przypisywany ciągowi wc -l work.txt, zamiast tego przypisywany jest numer 201.
Ignis
Zasób powiązany: 3.5.4 Zastępowanie poleceń w podręczniku Bash .
Eliah Kagan

Odpowiedzi:

2

Aby ocenić wyrażenie, musisz użyć odwrotnych klawiszy.

$ num=`wc -l sample.txt`
$ echo $num
1 sample.txt

Jeśli chcesz zobaczyć tylko „1” na wyjściu, użyj polecenia

$ num=`cat sample.txt | wc -l`
$ echo $num
1

A także działa:

$ num=`wc -l < sample.txt`
$ echo $num
1

Aby uzyskać dodatkowe informacje, zobacz Różnice między podwójnymi cudzysłowami „”, pojedynczymi cudzysłowami ”i odwrotnymi wierszami„ ”w wierszu poleceń?

Danatela
źródło
Masz pojęcie, dlaczego otrzymuję „1 sample.txt”, a nie tylko „1”?
JohnMerlino,
W ten sposób wcdziała polecenie. Spróbować cat sample.txt | wc -l.
Danatela
wc -l wyświetla liczbę linii obecnych w pliku wraz z nazwą pliku.
Avinash Raj
5

Uwaga: ten symbol:

Pojedynczy cytat

   Enclosing characters in single quotes preserves the  literal  value  of
   each character within the quotes.  A single quote may not occur between
   single quotes, even when preceded by a backslash.

i

`

Backquote

   Command substitution allows the output of a command to replace the com
   mand name.  There are two forms:

          $(command)
   or
          `command`

   Bash performs the expansion by executing command and replacing the com
   mand  substitution  with  the  standard output of the command, with any
   trailing newlines deleted.

Więc Backquote zwraca wynik polecenia na Standard Output. Dlatego

`wc -l sample.txt`

zwraca wyniki polecenia, natomiast

„wc -l sample.txt”

po prostu zwróć „wc -l sample.txt” jak zwykle

Rozważ zrobienie tego jako przykładu:

$ A='wc -l /proc/mounts'
$ B=`wc -l /proc/mounts`
$ C=$(wc -l /proc/mounts)

A teraz echo wszystkich trzech zmiennych:

$ echo $A
wc -l /proc/mounts
$ echo $B
35 /proc/mounts
$ echo $C
35 /proc/mounts
c0rp
źródło
4

Jeśli chcesz przechwycić dane wyjściowe polecenia w zmiennej, musisz użyć odwrotnego ciągu ``lub dołączyć polecenie w $():

$ d=$(date)
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014
$ d=`date`
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014

Zauważ, że łańcuch jest faktycznie oceniany w momencie deklaracji zmiennej, a nie po jego powtórzeniu. Komenda jest w rzeczywistości uruchamiana w obrębie $()lub za pomocą tyknięć, a wynik tej komendy jest zapisywany jako wartość zmiennej.

Ogólnie rzecz biorąc, zawsze powinieneś używać $()zamiast backticków, które są przestarzałe i tylko ze względów kompatybilności i znacznie bardziej ograniczone. Nie możesz na przykład zagnieżdżać poleceń w ramach backticksa, ale możesz $():

$ echo $(date -d $(echo yesterday))
Sun Mar 16 10:26:07 CET 2014

Zobacz ten wątek na stronie U&L, aby dowiedzieć się więcej o tym, dlaczego ``należy tego unikać.

terdon
źródło
1
Zgadzam skrypty powinny preferować $( )do ` `. Ale jak mówi wag , cytaty tylne się zagnieżdżają. echo $(date -d $(echo yesterday))staje się echo `date -d \`echo yesterday\``; echo $(echo $(date -d $(echo yesterday)))staje się echo `echo \`date -d \\\`echo yesterday\\\`\``. Mówię, że to nie obala twojej tezy, ale ją wzmocni : uniknięte wewnętrzne cudzysłowy sprawiają, że ` `składnia jest silniejsza niż często się przyznaje, ale specjalne traktowanie \jest dziwne, zaskakujące i trudne do uzasadnienia. Z $( )tego, co można zobaczyć jest zwykle to, co dostajesz.
Eliah Kagan