web-dev-qa-db-ja.com

バッククォートコマンドのカプセル化

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

バッシュはどのようにそれをしますか?最初に、エスケープされていないバッククォートで式を実行し、それが返されるようです(二重引用符 ""は削除されますよね?):

`echo uh!`

したがって、次と同等の入力があります。

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

(補足:本当に、なぜそれが機能するのですか?理由:

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

次に、Bashはバッククォートで式を再度実行します。

test@debian:~$ echo uh!

最終的に出力が得られます。

uh!

そうですか?そして、どのようにしてfourecho- backtick-expressionを互いにカプセル化できるでしょうか?

2
wolf-revo-cats

bashのバージョンによって異なります:

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

bash-4.3では、!"は履歴イベント指定子としての資格がなくなったため、履歴拡張は適用されません。

それ以外は、通常のバッククォートのネスト構文です。バックティックの内部では、バックスラッシュ文字がオーバーロードされて(さらに)、ネストされた展開が再度実行されます。

必要な数のレベルをネストできます。

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

これは面倒な同等物です:

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

ただし、どちらのバージョンでも、コマンド置換はWord分割の対象となることに注意してください。だから、あなたはそれを防ぐためにそれらを引用したいと思うでしょう。

bashdashpdkshyashzshを使用すると、比較的簡単です。

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

ボーンシェルまたはコーンシェルでは、"もエスケープする必要があるため、次のようになります。

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

と比べて:

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

これは面白い。

これはええと拡張します:

_echo `echo \`echo uh\``
_

でもない

_echo "`echo \`echo uh\``"
_

内部膨張を抑制します。

bashシェルとPOSIXシェル(ダッシュ)の両方で、バックティックのネストに適した代替手段として$()があります。

興味深いことに、内部プロセス置換は、引用符で囲まれているかどうか、または内部置換がバッククォートまたは$()を使用しているかどうかに関係なく、$()で展開されません。

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

バックティックを使用した暗黙の拡張は、あまり安全に見えません。特にネストしたい場合は、$()に固執します。

2
PSkocik