~によると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 var
var=$(line)
bash
zsh
printf -v variable format args
zsh
stat
strftime
一部のシェルは一部の情報も生成します。すでにksh
's$SECONDS
および他のいくつかのシェルで見つかったいくつかの特殊変数(および、$RANDOM
などの標準変数(たとえば'sと同じ))で自動的に使用できます。$-
$#
fish
(count $argv)
では、zsh
これはほとんどのシェルの内部で一般化されているため、組み込みコマンドの出力にコマンド置換を使用する必要はほとんどありません。たとえば、組み込みコマンド、キーワード、コマンドリストなどの連想配列があります。
if (($+builtins[echo])); then
echo echo is a builtin
fi