サブシェルのないifステートメント内でのコマンド出力の比較

サブシェルのないifステートメント内でのコマンド出力の比較

~によるとhttps://www.gnu.org/software/bash/manual/bashref.html#Command-Grouping

中かっこの間にコマンドリストを配置すると、そのリストは現在のシェルのコンテキストで実行されます。

しかし、これを試してみると、if [[ { type -t echo; } = "builtin" ]]; then echo 1; else echo 0; fi次のエラーが発生します。

-bash: 条件付き二項演算子が必要です。

-bash: "type"の近くに構文エラーがあります。

大丈夫です、このように使用しないでください。今if [[ $( type -t echo ) = "builtin" ]]; then echo 1; else echo 0; fi理論的に。

サブシェルの不必要な使用を防ぐ方法に関する他の質問に対する答えが見つかりましたが、どちらもサブシェルなしでコマンドの出力を比較する方法を説明していません。私が本当に望むのは、不要なサブシェルを使用しないことです。可能であれば、現在のシェルコンテキストでこのチェックを実行したいと思います。そうしなければならないと感じられます。 PS 他の方法がない場合は、変数と操作を使用しても問題ありません。

ベストアンサー1

コマンドの出力を取得するには何とか読み取る必要があります。type標準出力に書き込みます。何とかインポートして[コマンドに渡す必要があります。

$(...)これにはパイプを使用してください。ただし、パイプの場合はビルダーとリーダーのプロセスが必要なため、組み込みコマンドを実行してもプロセスを分岐する必要があります。同じプロセスでパイプを読み書きしようとすることができますが、誰も読み取らないと書き込みがブロックされる可能性があるため、デッドロックが発生しやすくなりますtype

yashネイティブインターフェイスを持つシェルを使用してこれを実行できますpipe()

{
  type echo >&3
  echo 3>&- # close the writing end so the reader can see an eof
  IFS= read -r answer <&4
} 3>>|4

type上記で、出力がパイプバッファサイズ(最新バージョンのLinuxではデフォルトは64KiB)より大きい場合、デッドロックが発生します。

を使用すると、bashいつでも次のことができます。

type -t echo > file
IFS= read -rd '' type < file
if [ "$type" = builtin ]...

しかし、これはサブシェルを防ぎますが、ファイルシステムがfile

これはtype組み込みです。その出力はシェルによって生成され、実際にシェルでその出力を使用するためにプロセスをフォークする必要があるのは少し愚かな感じです。

一部のシェル(ksh93およびfish)はそこにいくつかの最適化を実装しています。$(type echo)(type echo)in)では、fish実際には出力の書き込みと読み取りを偽造します(FreeBSDはshまた、単一の組み込み呼び出しに対してこれを行います(typeここでのように))。組み込み関数のstdoutがコマンド置換である場合、シェルは出力を作成しませんが、可能な出力のテキストをコマンド置換結果に追加するため、フォークは必要ありません。

実際、fish'sはサブシェル環境も作成しないという点で's(type echo)に似ています。そして、ksh93${ type echo;}$(...)ksh93 編むサブプロセスが内部コードを解釈するために分岐したように見えるようにするサブシェル環境であり、バリアントにはそうしません${ ...;}

ksh93$ a=1
ksh93$ echo "$(a=2; type echo) $a"
echo is a shell builtin 1
ksh93$ echo "${ a=3; type echo;} $a"
echo is a shell builtin 3

fish> set a 1
fish> echo (set a 2; type echo) $a
echo is a builtin 2

最適化されていない一部のシェルでは、結果を作成せずに変数に保存して、多くの組み込み関数を呼び出すことができます。

最も明白なのは標準readであり、基本的にこれを行います(代わりにgetoptsこれを行います)。そして、...、組み込み関数を使用して同じことを行うことができます。IFS= read -r varvar=$(line)bashzshprintf -v variable format argszshstatstrftime

一部のシェルは一部の情報も生成します。すでにksh's$SECONDSおよび他のいくつかのシェルで見つかったいくつかの特殊変数(および、$RANDOMなどの標準変数(たとえば'sと同じ))で自動的に使用できます。$-$#fish(count $argv)

では、zshこれはほとんどのシェルの内部で一般化されているため、組み込みコマンドの出力にコマンド置換を使用する必要はほとんどありません。たとえば、組み込みコマンド、キーワード、コマンドリストなどの連想配列があります。

if (($+builtins[echo])); then
  echo echo is a builtin
fi

おすすめ記事