編集:元のタイトルは「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
$
Manページで失敗する理由が見つかりませんでした。
bash
パイプラインの右側を実行サブシェルコンテキスト なので、変数に変更します(これはread
が行うことです)保存されません—コマンドの最後でサブシェルが死ぬと死にます。
代わりに、 プロセス置換 を使用できます。
$ read a b dump < <(echo 1 2 3 4 5)
$ echo $b $a
2 1
この場合、read
はプライマリシェル内で実行され、出力生成コマンドはサブシェルで実行されます。 <(...)
構文 creates サブシェルを使用して、その出力をパイプに接続します。パイプは、通常の <
操作でread
の入力にリダイレクトされます 。 read
はメインシェルで実行されたため、変数は正しく設定されています。
コメントで指摘されているように、目的が文字列を何らかの方法で変数に分割することである場合は、 here string を使用できます。
read a b dump <<<"1 2 3 4 5"
それ以外にもあると思いますが、ない場合はこれがより良い選択肢です。
bash
はPOSIX
とbash
の両方の動作を許可するため、これはksh
のバグではありません。
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