Чи застаріли задні посилання (тобто `cmd`) у оболонках * sh?


118

Я багато разів бачив цей коментар на Unix & Linux, а також на інших сайтах, які використовують фразу "backticks depreciated", стосовно оболонок, таких як Bash & Zsh.

Чи це твердження правдиве чи помилкове?


Див. Чому не повернулися цитати в скрипті оболонки, допомагають мені cdв каталог для прикладу того, чому $(...)нотацію простіше використовувати, ніж вкладені зворотні лапки.
Джонатан Леффлер


1
Принаймні один Unix, AIX, задокументував, що backticks є застарілим . "Хоча синтаксис зворотного котирування прийнято ksh, він вважається застарілим стандартами X / Open Portability Guide Issue 4 та POSIX. Ці стандарти рекомендують портативним програмам використовувати синтаксис $ (команда)." ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.osdevice/…
Крістофер

У мене є певна різниця в "GNU bash, версія 3.2.57 (1) -випуск (x86_64-apple-darwin14)" на Mac 10.10: matchingLines=$( grep -n '\$-PARAMETER' ... | ... )працює, matchingLines= backtick the same stuff backtickне працює - схоже, втрачає зворотний косий кут нахилу в доларі. (Це не мій сценарій ...)
денис

Відповіді:


126

Є два різних значення "застарілий".

бути застарілим: (головним чином, функція програмного забезпечення) може бути придатною для використання, але вважатись застарілою та найкраще уникати її, як правило, через її заміщення.

—Новий Оксфордський американський словник

За цим визначенням зворотних лапок є застарілими.

Нездатний статус також може означати, що функція буде видалена в майбутньому.

- Вікіпедія

За цим визначенням backticks не застаріли.

Все ще підтримується:

Посилаючись на специфікацію відкритої групи щодо мов командної оболонки , зокрема розділу "2.6.3 Заміна команд", можна помітити, що обидві форми підстановки команд, backticks ( `..cmd..`) або доларові парени ( $(..cmd..)) все ще підтримуються настільки, наскільки йде специфікація.

витяг

Підстановка команд дозволяє замінити результат команди замість самої назви команди. Заміна команди відбувається, коли команда додається наступним чином:

          $(command)

          or (backquoted version):

          `command`

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

У зворотному котируваному стилі підстановки команд < backslash > зберігає своє буквальне значення, за винятком випадків, коли слідує: '$', ' \`' або <backckslash> . Пошук відповідного зворотного котирування повинен задовольнятися першим незапропонованим цитатам, що не залишилося цитатами; під час цього пошуку, якщо в коментарі оболонки зустрічається невиконаний зворотний цитат, відбувається тут документ, вбудована команда заміни $(command)форми або рядка, що цитується, не визначені результати. Рядок з одноцитованим або подвійним цитуванням, який починається, але не закінчується, в " `...`" послідовності створює невизначені результати.

З $(command)формою всі символи, що слідують за відкритими дужками на відповідні дужки, що закриваються, складають команду. Будь-який дійсний скрипт оболонки може використовуватися для команди, за винятком сценарію, що складається виключно з повторних вказівок, які дають не визначені результати.

То чому тоді всі кажуть, що прихильність застаріла?

Оскільки в більшості випадків використання має використовуватися форма доларових парен замість задньої частини. (Зникла в першому сенсі вище.) Багато найповажніших сайтів (включаючи U&L) часто заявляють про це також у всьому світі, тому це слушна порада. Цю пораду не слід плутати з деяким неіснуючим планом вилучення підтримки штрихів із оболонок.

ПРИМІТКА. Цей третій уривок (вище) показує декілька ситуацій, коли задні посилання просто не працюватимуть, але працює новіший метод доларових парен, починаючи з наступного абзацу:

Крім того, синтаксис, що коментується, має історичні обмеження щодо вмісту вбудованої команди. Хоча новіша форма "$ ()" може обробляти будь-який вид допустимого вбудованого сценарію, форма, що коментується, не може обробляти деякі дійсні сценарії, що містять зворотні котирування.

Якщо ви продовжуєте читати цей розділ, відмови виділяються, показуючи, як вони не зможуть використовувати задні посилання, але працюйте, використовуючи нові позначення паренів долара.

Висновки

Тому бажано, щоб ви використовували доларові парени замість задніх планок, але ви насправді не використовуєте те, що технічно "застаріло", як у "це перестане працювати повністю в якийсь запланований момент".

Прочитавши все це, ви повинні мати рішення, яке вам настійно рекомендується використовувати доларові парени, якщо вам спеціально не потрібна сумісність із справжньою оригінальною оболонкою, яка не є POSIX Bourne.


26
За більшої частини значень засуджується , я (і ви) хотів би сказати , що зворотні лапки є застарілими. Це здебільшого термінологічне питання.
Стефан Шазелас

4
@StephaneChazelas - Погодився! Я продовжую розповідати ppl, що вони застаріли, але backticks офіційно не "застаріли" в тому сенсі, що найближчим часом вони будуть активно вилучатися з кодової бази будь-якої оболонки. Принаймні жодного, що мені відомо.
slm

3
Моя інтерпретація полягає в тому, що зворотні котирування підтримуються виключно тому, що вони занадто закріплені в існуючому коді, щоб офіційно застаріти. Я ніколи не чув аргументу, щоб продовжувати використовувати їх у новому коді.
чепнер

3
@slm Так, я думаю, ти це отримав - я відтягнувся і не помітив. Використовувати ці речі майже немає причин, за винятком того, що він може бути лише трохи чистішим, коли шарувати шарики, так що $( cmd `cmd`)це трохи менше безладно, ніж $( cmd $(cmd))- це легше читати. Я завжди вважав застарілу функцію програмного забезпечення однією з офіційно позначених для видалення вгору за течією - і ніколи не чув про щось подібне. Мені байдуже - не маю любові до могили.
mikeserv

3
Ви можете додати наступну цитату із стандартного обґрунтування POSIX : Через такі непослідовні поведінки різноманітні підстановки команд не рекомендуються для нових програм, які вкладають підстановки команд або намагаються вставити складні сценарії. Хоча це не формальна депресія, оскільки розділ обґрунтування є інформативним та ненормативним, але це дозволяє припустити, що слід уникати подальшого використання підстав.
jw013

15

Це не застаріло, але backticks ( `...`) - це застарілий синтаксис, який вимагається лише найстарішим з не сумісних з POSIX сумісними оболонками, і $(...)є 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`

    оскільки $()використовує абсолютно новий контекст для цитування

    який не є портативним, оскільки оболонки Борна та Корна вимагатимуть цих зворотних нахилів, в той час як Bash і Dash цього не роблять.

  • Синтаксис для гніздових підстановок команд простіше:

    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
  • Синтаксис зворотних посилань має історичні обмеження щодо вмісту вбудованої команди і не може обробляти деякі дійсні сценарії, що містять зворотні котирування, в той час як новіша $()форма може обробляти будь-який дійсний вбудований сценарій.

    Наприклад, ці вбудовані інакше вбудовані сценарії не працюють у лівій колонці, але працюють у правій 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 ')'
    `                              )

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

Джерело: Чому $(...)віддається перевага над `...`(заднім числом)? на BashFAQ

Дивитися також:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.