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
によるバグではありません。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