Оценка строки в сценарии оболочки

8

Я следую этому руководству по написанию скриптов в bash:

В разделе Числовые сравнения он приводит пример:

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

То, что происходит выше, это то, что мы храним строку команд в переменной bash, а затем вызываем echo для этой переменной. Кажется, что происходит, когда строка вычисляется и команда wc выполняется и возвращает количество строк в управляющий терминал.

Итак, я запускаю свой терминал в Ubuntu 12.04 и пробую что-то похожее:

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

Подождите секунду, это не оценило строку и вернуло количество строк. Это просто повторило строку обратно в терминал. Почему я получил разные результаты?

JohnMerlino
источник
Обратите внимание, что num никогда не присваивается строка wc -l work.txt, вместо этого ей присваивается номер 201.
ignis
Связанный ресурс: 3.5.4 Подстановка команд в справочном руководстве Bash .
Элия ​​Каган

Ответы:

2

Вы должны использовать обратные пометки, чтобы оценить выражение.

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

Если вы хотите видеть только «1» в выводе, используйте команду

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

А также работает:

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

Для получения дополнительной информации см. Различия между двойными кавычками "", одинарными кавычками '' и обратными кавычками ´ ´ в командной строке?

Danatela
источник
Любая идея, почему я получаю «1 sample.txt», а не только число «1»?
ДжонМерлино
Так wcработает команда. Попробуй cat sample.txt | wc -l.
Данатела
wc -l отображает количество строк в файле вместе с именем файла.
Авинаш Радж
5

Пожалуйста, обратите внимание, что символ:

'

Одинарные цитаты

   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.

а также

`

кавычка

   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.

Таким образом, Backquote возвращает результат команды в стандартный вывод. Поэтому

`wc -l sample.txt`

возвращает результаты команды, а

'wc -l sample.txt'

просто верните "wc -l sample.txt" как обычную строку

Рассмотрим это в качестве примера:

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

А теперь повторить все три переменные:

$ echo $A
wc -l /proc/mounts
$ echo $B
35 /proc/mounts
$ echo $C
35 /proc/mounts
c0rp
источник
4

Если вы хотите записать вывод команды в переменную, вам нужно либо использовать обратные пометки, ``либо заключить команду в $():

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

Обратите внимание, что строка на самом деле вычисляется в момент объявления переменной, а не когда вы ее выводите. Команда на самом деле выполняется в пределах $()или кавычек, и выходные данные этой команды сохраняются как значение переменной.

В общем, вы должны всегда использовать $()вместо обратных ссылок, которые устарели и только вокруг по причинам совместимости и гораздо более ограниченным. Вы не можете, например, вкладывать команды в обратные трюки, но вы можете сделать это с помощью $():

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

Посмотрите эту ветку на U & L для более подробной информации о том, почему ``следует избегать.

terdon
источник
1
Я согласен скрипты должны предпочесть , $( )чтобы ` `. Но, как говорит шутник, обратные кавычки действительно гнездятся. echo $(date -d $(echo yesterday))становится echo `date -d \`echo yesterday\``; echo $(echo $(date -d $(echo yesterday)))становится echo `echo \`date -d \\\`echo yesterday\\\`\``. Я говорю, что это не опровергает ваш тезис, а укрепляет его : экранированные внутренние обратные кавычки делают ` `синтаксис более мощным, чем часто допускается, но особая трактовка \странного, удивительного и трудного рассуждать. С того, $( )что вы видите, как правило , то , что вы получите.
Элия ​​Каган