bashで中括弧のグループコマンドをパイプでつなぐとサブシェルで実行されるので一応気をつける

Pocket
LINEで送る

どうも。寝不足太郎上田です。細かい話が嫌いなのですが、調べる必要があり、調べたことを書きます。

{}で囲ったグループコマンドについてはシェルスクリプト本体と同じプロセスで動作するという記述がmanにあります。

ueda@remote:~$ man bash
...
       { list; }
              list is simply executed in the current shell environment.  
...

私の場合、グループコマンドはパイプに複数のコマンドを渡すときに使います。こんな感じで。

{
    echo ファイルのヘッダだよーん
    cat file
    echo ファイルのフッタだよーん
}        |
cat -n 

ただ、こういうときはmanのとおりの同じプロセスでは動いていないんじゃないかと。なぜなら、パイプでグループコマンドをつなぐときに、別プロセスにする方がパイプを楽に繋げることができるからです。

ということで実験。bash4からBASHPIDという変数があって、これがサブシェルのプロセスIDを持っているので、こいつをechoしてみます。$$だとサブシェルでもシェルスクリプト本体のプロセスIDを保持し続けるのでこの実験はできません。

パイプでつながない場合

ueda@remote:~$ cat hoge.bash 
#!/bin/bash

echo 親: $BASHPID

{
	echo 子: $BASHPID
}
ueda@remote:~$ ./hoge.bash 
親: 1671
子: 1671

同じプロセスです。

パイプでつなぐ場合

ueda@remote:~$ cat hoge2.bash 
#!/bin/bash

echo 親: $BASHPID

{
	echo 子: $BASHPID
} | cat
ueda@remote:~$ ./hoge2.bash 
親: 1706
子: 1707

サブシェルですね。

ということは、次のように子供で定義した変数は親から見えません。こんな使い方しませんが、一応気をつけておいた方が良さそうです。

ueda@remote:~$ cat hoge2-2.bash 
#!/bin/bash

echo 親: $BASHPID

{
	A=aaa
	echo 子: $BASHPID
} | cat

echo $A
ueda@remote:~$ ./hoge2-2.bash 
親: 1836
子: 1837
              <- aaaと出てこない

丸括弧だと

次のようにデフォルトでサブシェルです。

ueda@remote:~$ cat hoge3.bash 
#!/bin/bash

echo 親: $BASHPID

(
	echo 子: $BASHPID
) 
ueda@remote:~$ ./hoge3.bash 
親: 1758
子: 1759

ご相談

これは自明だからmanに書かないんでよいんですかね??in the current shell environmentというのがサブシェル云々の話とは違う話なのかな??どうしよう・・・。

気が小さいのでドキドキするだけで放置・・・。うーん。

Pocket
LINEで送る