web-dev-qa-db-ja.com

メインシェルでコマンドブロックを実行するにはどうすればよいですか?

私はメインシェル内で全体として一連のコマンドを実行しようとしますが、私が教えられた方法はサブシェル内でのみ機能します。

???? echo $BASHPID
18884
???? (echo "hello $BASHPID";sleep 5;echo "hello again $BASHPID")
hello 22268
hello again 22268

私も試しました:

. (echo "hello $BASHPID";sleep 5;echo "hello again $BASHPID")
source (echo "hello $BASHPID";sleep 5;echo "hello again $BASHPID")

ソースコマンドを使用するのは、スクリプトがメインシェル内で実行されるようにするためです。

コマンドをファイル内に置き、それをソースコマンドで実行すれば機能すると思いますが、スクリプトファイルを回避する方法があるかどうかを知りたいです。

8
sharkant

サブシェルでsomethingを起動する( something )の代わりに、現在のシェルでsomethingを起動する{ something ; }を使用します

{の後にスペースが必要で、;の前に}(または改行)も必要です。

例:

$ { echo "hello $BASHPID";sleep 5;echo "hello again $BASHPID" ; }
hello 3536
hello again 3536

ただし、いくつかの複雑なコマンド(またはパイプされたコマンド)を起動した場合、ほとんどの場合、それらはサブシェルにあることに注意してください。

そして、現在のシェルのpidを取得する「ポータブル」な方法は$$です。

したがって、代わりに次のようにテストを記述します。

{ echo "hello $$"; sleep 5 ; echo "hello again $$" ; }

(睡眠はとにかくここでは本当に役に立ちません)

10
Olivier Dulac

全体としての意味に依存します。

シェルにいくつかのコマンドを送信するだけで、すべてのコマンドを入力するまでシェルがコマンドの実行を開始しないことを確認する場合は、次のようにすることができます。

cmd1; cmd2

または

cmd1Ctrl+VCtrl+Jcmd2

(またはブラケット貼り付けを有効にします(bind 'set enable-bracketed-paste on')を使用して、括弧で囲まれた貼り付けをサポートする端末からコマンドを貼り付けます。

または:

{
cmd1
cmd2
}

それらを複数の行に配置する。

たとえば、同じstdinまたはstdoutを共有するようにグループ化する場合は、次のように使用できます。

{ cmd1; cmd2; } < in > out

または

eval 'cmd1; cmd2' < in > out

bashにはzshの無名関数に相当するものがないため、独自の変数とオプションのスコープで実行する場合は、一時的な関数を定義する必要があります。

f() { local var; var=foo; bar;}; f
12