В чем преимущество использования $() вместо обратных кавычек в сценариях оболочки?

StackOverflow https://stackoverflow.com/questions/9449778

  •  13-11-2019
  •  | 
  •  

Вопрос

Существует два способа захвата вывода командной строки в bash:

  1. Обратные кавычки оболочки Legacy Bourne ``:

     var=`command`
    
  2. $() синтаксис (который, насколько я знаю, специфичен для Bash или, по крайней мере, не поддерживается старыми оболочками, отличными от POSIX, такими как оригинальный Bourne)

     var=$(command)
    

Есть ли какая-либо польза от использования второго синтаксиса по сравнению с обратными кавычками?Или они полностью эквивалентны на 100%?

Это было полезно?

Решение

Основная способность Nest их, команды внутри команд, не теряя здравомыслия, пытаясь выяснить, будет ли какая-то форма сбережения на задних концах.

Пример, хотя несколько надуманный:

deps=$(find /dir -name $(ls -1tr 201112[0-9][0-9]*.txt | tail -1l) -print)
.

Что даст вам список всех файлов в дереве каталогов /dir, которые имеют то же имя, что и самый ранний датированный текстовый файл с декабря 2011 года (a) .

Другой пример будет что-то вроде получения имени (не полный путь) родительского каталога:

pax> cd /home/pax/xyzzy/plugh
pax> parent=$(basename $(dirname $PWD))
pax> echo $parent
xyzzy
.


(a) теперь, когда Command Command может на самом деле не работать, я не проверил функциональность.Итак, если вы проголосуете меня за это, вы потеряли зрелище намерения :-) Он предназначен так же, как иллюстрация, как к тому, как вы можете гнать, а не как безрезультатно, готовый фрагмент.

Другие советы

Предположим, вы хотите найти каталог lib, соответствующий там, где установлен gcc.У вас есть выбор:

libdir=$(dirname $(dirname $(which gcc)))/lib

libdir=`dirname \`dirname \\\`which gcc\\\`\``/lib
.

Первый проще, чем второй - используйте первый.

Обратные кавычки (`...`) — это устаревший синтаксис, необходимый только для самых старых из несовместимых с POSIX Bourne-оболочек и $(...) является POSIX и более предпочтителен по нескольким причинам:

  • обратная косая черта (\) внутренние обратные кавычки обрабатываются неочевидным образом:

    $ 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 \\
    
  • Вложенное цитирование внутри $() гораздо удобнее:

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

    вместо:

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

    или написать что-то вроде:

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

    потому что $() использует совершенно новый контекст для цитирования

    который не является переносимым, поскольку оболочки Bourne и Korn потребуют этих обратных косых черт, а Bash и тире - нет.

  • Синтаксис вложенных подстановок команд проще:

    x=$(grep "$(dirname "$path")" file)
    

    чем:

    x=`grep "\`dirname \"$path\"\`" file`
    

    потому что $() обеспечивает совершенно новый контекст для цитирования, поэтому каждая замена команды защищена и может обрабатываться отдельно, не беспокоясь о цитировании и экранировании.Использование обратных кавычек становится все уродливее и уродливее после двух и более уровней.

    Еще несколько примеров:

    echo `echo `ls``      # INCORRECT
    echo `echo \`ls\``    # CORRECT
    echo $(echo $(ls))    # CORRECT
    
  • Это решает проблему несогласованного поведения при использовании обратных кавычек:

    • echo '\$x' результаты \$x
    • echo `echo '\$x'` результаты $x
    • echo $(echo '\$x') результаты \$x
  • Синтаксис обратных кавычек имеет исторические ограничения на содержимое встроенной команды и не может обрабатывать некоторые допустимые сценарии, включающие обратные кавычки. $() form может обрабатывать любой действительный встроенный скрипт.

    Например, эти действительные встроенные сценарии не работают в левом столбце, но работают в правом.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 ')'
    `                              )
    

Поэтому синтаксис для $-с префиксом замена команды должен быть предпочтительным методом, поскольку он визуально понятен и имеет чистый синтаксис (улучшает читабельность для человека и компьютера), он является вложенным и интуитивно понятным, его внутренний анализ является отдельным, а также он более согласован (со всеми другими расширениями, которые анализируются изнутри). двойные кавычки), где обратные кавычки являются единственным исключением и ` персонаж легко замаскируется, если находится рядом с " что еще больше затрудняет чтение, особенно если шрифт мелкий или необычный.

Источник: Почему $(...) предпочтительнее `...` (обратные кавычки)? на БашFAQ

Смотрите также:

от человека bash:

          $(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.  Embedded newlines are not deleted, but they
   may  be  removed during word splitting.  The command substitution $(cat
   file) can be replaced by the equivalent but faster $(< file).

   When the old-style backquote form of substitution  is  used,  backslash
   retains  its  literal  meaning except when followed by $, `, or \.  The
   first backquote not preceded by a backslash terminates the command sub-
   stitution.   When using the $(command) form, all characters between the
   parentheses make up the command; none are treated specially.
.

В дополнение к другим ответам,

$(...)
.

выделяется визуально лучше, чем

`...`
.

backticks выглядят слишком похожи на апострофы;Это варьируется в зависимости от шрифта, который вы используете.

(и, как я только что заметил, backticks намного сложнее входить в встроенные образцы кода.)

$() позволяет вложению.

out=$(echo today is $(date))
.

Я думаю, что backticks не позволяют этому.

Это стандарт POSIX, определяющий $(command) форма замены команд.Большинство используемых сегодня оболочек совместимы с POSIX и поддерживают эту предпочтительную форму вместо архаичной обратной кавычки.А замена команды раздел (2.6.3) документа Shell Language описывает это:

Подстановка команд позволяет заменить вывод команды вместо самого имени команды.Замена команды должна происходить, когда команда заключена следующим образом:

$(команда)

или (версия в обратных кавычках):

`команда`

Оболочка должна расширить подстановку команд, выполнив командав среде подоболочки (см. Среда выполнения оболочки) и замена замены команды (текст команда плюс вкладывая «$ ()» или Backquotes) со стандартным выводом команды, удаление последовательностей одного или нескольких <newline> персонажи в конце замены.Встроенный <newline> символы до конца вывода не должны быть удалены;Тем не менее, они могут рассматриваться как полевые разделители и устранять во время расщепления полевых действий, в зависимости от значения IFS и цитирования, которое действует.Если выход содержит какие -либо нулевые байты, поведение не определен.

В стиле подстановки команд в обратных кавычках: <backslash> сохранить свое буквальное значение, за исключением случаев, когда следовало:'$' , '`', или <backslash>.Поиск соответствующего обратного квадрата должен быть удовлетворен первым невозможным не вмешанным обратным кводом;Во время этого поиска, если в комментарии на оболочке встречается неэкрасная обратная квоот, здесь документ, встроенная командная замена $ (команда) форма или цитируемая строка, возникают неопределенные результаты.Одноцитированная или цитируемая или цитируемая строка, которая начинается, но не заканчивается, внутри "`...`«Последовательность дает неопределенные результаты.

С $(команда) Форма, все символы, следуя открытой скобке с подходящим закрытием скобки, составляют команда.Для этого можно использовать любой допустимый сценарий оболочки. команда, кроме сценария, состоящего исключительно из перенаправлений, которые дают неопределенные результаты.

Результаты замены команды не должны обрабатываться для дальнейшего расширения тилде, расширения параметров, замены команд или арифметического расширения.Если замена команды происходит внутри двойных цитат, расщепление поля и расширение пути не должно выполняться на результатах замены.

Подстановка команд может быть вложенной.Чтобы указать гнездование в пределах версии Back -Quard, приложение должно предшествовать внутренним переходным <backslash> персонажи;например:

\`команда\`

Синтаксис командного языка оболочки неоднозначен для расширений, начинающихся с «$((", что может ввести арифметическое расширение или замену команды, которая начинается с подборной.Арифметическое расширение имеет приоритет;То есть оболочка должна сначала определить, может ли она проанализировать расширение как арифметическое расширение и должна анализировать расширение как замену команды, если оно определяет, что оно не может проанализировать расширение как арифметическое расширение.Оболочке не нужно оценивать вложенные расширения при выполнении этого определения.Если он сталкивается с концом ввода, не определив, что он не может проанализировать расширение как арифметическое расширение, оболочка должна рассматривать расширение как неполное арифметическое расширение и сообщать об ошибке синтаксиса.Соответствующее приложение должно гарантировать, что оно разделяет "$(" и '(«В два жетона (то есть разделить их с помощью белого пространства) в замене команды, которая начинается с подборной.Например, подстановку команды, содержащую одну подоболочку, можно записать так:

$( (команда) )

Это наследие вопрос, но я придумал совершенно действительный пример генеракодицетагкода над $(...).

Я использовал удаленный рабочий стол к Windows, запущенную Cygwin и хотел повторять в результате команды.К сожалению, характером заднего понятия невозможно было войти либо из-за удаленного рабочего стола или самого Cygwin.

Это змеемое, чтобы предположить, что знак доллара и скобки будут легче ввести в такие странные настройки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top