Инкапсуляция команды Backtick

test@debian:~$ echo `echo \`echo "uh!"\`` uh! 

Как это делает Баш? Кажется, что он сначала выполняет выражение в неэкранированных обратных тактах, которое возвращает (двойные кавычки «" удаляются, правильно?):

 `echo uh!` 

Таким образом, у нас есть входной эквивалент:

 test@debian:~$ echo `echo uh!` 

(обратите внимание: действительно, почему это работает? Потому что:

 test@debian:~$ echo `echo uh!` -bash: !`: event not found 

)

Затем Bash снова выполняет выражение в backticks, которое дает:

 test@debian:~$ echo uh! 

Что, наконец, дает нам выход:

 uh! 

Это правильно? И как можно было инкапсулировать четыре выражения echo -backtick-друг в друга?

Зависит от вашей версии bash :

 bash-4.2$ echo `echo \`echo "uh!"\`` bash: !"\``: event not found bash-4.3$ echo `echo \`echo "uh!"\`` uh! 

В bash-4.3 !" Больше не подходит в качестве указателя события истории, поэтому расширение истории не применяется.

Кроме этого, это просто обычный синтаксис вложенности backtick backtick. Внутри backticks символ обратной косой черты перегружен (еще раз), чтобы повторить это вложенное расширение.

Вы можете вложить столько уровней, сколько хотите:

 echo `echo \`echo \\\`echo \\\\\\\`echo whatever\\\\\\\`\\\`\`` 

Какой громоздкий эквивалент:

 echo $(echo $(echo $(echo $(echo whatever)))) 

Однако обратите внимание, что в обеих версиях подстановка команды подлежит разбиению на слова. Итак, вы хотите процитировать их, чтобы предотвратить это.

С bash , dash , pdksh , pdksh , zsh , это относительно легко:

 echo "`echo "\`echo "\\\`echo "\\\\\\\`echo whatever\\\\\\\`"\\\`"\`"`" 

С оболочкой Bourne или Korn вам также нужно избегать " хотя, так что это становится:

 echo "`echo \"\`echo \\\"\\\`echo \\\\\\\"\\\\\\\`echo whatever\\\\\\\`\\\\\\\"\\\`\\\"\`\"`" 

Сравнить с:

 echo "$(echo "$(echo "$(echo "$(echo whatever)")")")" 

Это интересно.

Это расширяется до uh:

 echo `echo \`echo uh\`` 

и даже

 echo "`echo \`echo uh\``" 

подавляет внутреннее расширение.

Как в bash и в POSIX-оболочках (тире) у вас есть $() в качестве альтернативы обратным вызовам, поддерживающей вложенность.

Интересно, что внутренняя замена процесса не расширяется с помощью $() независимо от того, цитируется она или нет, или внутренняя подстановка использует обратные ссылки или $() :

 $ echo $(echo \$\(echo uh\)) $(echo uh) $ echo $(echo \`echo uh\`) `echo uh` 

Неявное расширение с backticks не выглядит очень безопасным. Я бы придерживался $() , особенно если вы хотите вложить.