Bashでは、パイプが値を設定しなかった後に読み込みます。

Bashでは、パイプが値を設定しなかった後に読み込みます。

kshの場合、値を区別するための便利な方法としてreadを使用します。

$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a 
2 1
$

しかし、Bashでは失敗します。

$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a 
  
$

マニュアルページで失敗の理由が見つかりませんでした。どんなアイデアがありますか?

答え1

bash パイプラインの右側を実行します。サブシェルのコンテキストしたがって、変数への変更(完了した操作read)は維持されません。コマンドの最後にサブシェルが保存されると消えます。

代わりに、次のものを使用できます。プロセスの交換:

$ read a b dump < <(echo 1 2 3 4 5)
$ echo $b $a
2 1

この場合、readデフォルトシェルで実行され、出力生成コマンドはサブシェルで実行されます。<(...)文法作るreadサブシェルを作成し、出力をパイプに接続して通常の入力にリダイレクトします。<仕事readメインシェルで実行されているため、変数が正しく設定されています。

コメントで指摘したように、実際に文字列を何らかの方法で変数に分割することが目標である場合は、次のようになります。ここにある文字列:

read a b dump <<<"1 2 3 4 5"

やるべきことがあると思いますが、そうでない場合はこれがより良い選択です。

答え2

これは、ユーザーが観察した不幸な違いを引き起こす権限や動作bashによるバグではありません。POSIXbashksh

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12

さらに、マルチコマンドパイプラインの各コマンドはサブシェル環境にありますが、拡張機能によってパイプラインの一部またはすべてのコマンドを現在の環境で実行できます。他のすべてのコマンドは、現在のシェル環境内で実行する必要があります。

ただしbash 4.2、最新バージョンでは、lastpipe非対話型スクリプトでこのオプションを設定して予想される結果を得ることができます。たとえば、次のようになります。

#!/bin/bash

echo 1 2 3 4 5 | read a b dump
echo before: $b $a 
shopt -s lastpipe
echo 1 2 3 4 5 | read a b dump
echo after: $b $a 

出力:

before:
after: 2 1

関連情報