スクリプト関数呼び出し: function と $(function)

スクリプト関数呼び出し: function と $(function)

簡単にするために次のコードを参考にします

#!/bin/bash

number=7

function doSomething() {
  number=8
}

doSomething
echo "$number"

印刷されます8

しかし、

#!/bin/bash

number=7

function doSomething() {
  number=8
}

$(doSomething)
echo "$number"

印刷されます7

以下の質問があります:

  • 何ですか技術名称それぞれについて?functioncallつまり$(functioncall)
  • それぞれのアプローチはどのように機能するのでしょうか?前者は関数自体の外側の変数を考慮し(影響し)、後者は考慮しないようです。
  • どちらかのアプローチを他方よりも使用することが必須な場合 (もちろん、パフォーマンスの問題が主な理由です)、その他の理由がある場合は、それも歓迎します。

答え1

コマンド置換の微妙な点を体験しています。

呼び出し

doSomething

は単純な関数呼び出しです。関数のコマンドを呼び出し場所にコピーして貼り付けたのとほぼ同じように、関数を実行します。したがって、変数はnumber新しい値で上書きされます8

呼び出し

$(doSomething)

一方ではコマンド置換機能を実行するためのものであり、関数が出力したものを返す stdout通常は「スタンドアロン」ではなく、変数の割り当てで使用されます。例:

os_type=$(uname)

これにより、コマンド が実行され、Linux システムではコンソールにuname出力され、その結果がシェル変数 に格納されます。したがって、 のように何も出力しないコマンドや関数でコマンド置換を使用するのは意味がありません。実際、置換は基本的に の出力のプレースホルダーであるため、そこでスクリプト エラーが発生しない唯一の理由は、関数が何も出力しないからです。たとえば、次のように記述したとします。Linuxos_typedoSomething$(doSomething)doSomething

$(uname)

の代わりに

$(doSomething)

シェルはコマンドを実行しようとしてLinux

Linux: No such file or directory

エラー(1)

観察した効果を理解するための重要なポイントは、コマンド置換では、コマンドはサブシェルで実行されるつまり、変数に加えられた変更は、メイン スクリプトを実行するシェルにバックプロパゲートされません。したがって、内部的には のコマンドを実行しdoSomething、変数numberを に設定します8が、これはスクリプトを実行するシェル プロセスとは関係のない独自のシェル プロセスで行われます ( が取得されるという事実を除く)。したがって、メイン スクリプトで使用したstdout変数を変更することはできません。number

さらに詳しく知りたい方は、

このサイト、または

より詳しい概要については、こちらをご覧ください。


(1)一方、これは、スクリプトを書いた時点では名前がわからないコマンドでも、コマンド置換を使用して、別のコマンドを実行することでそのコマンドの名前がわかるということを意味します。

関連情報