bashでは、パイプが値を設定していない後に読み取られます


22

編集:元のタイトルは「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ページで見つけられませんでした。


2
これは、GregのBash FAQの024ページで(やや不明瞭に)議論されています
スコット14

回答:


27

bash パイプラインの右側に実行サブシェルコンテキストをので(何である変数を変更し、readない)に保存されていない-彼らは、コマンドの最後に、サブシェルがないときに死にます。

代わりに、プロセス置換を使用できます。

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

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

コメントで指摘されているように、文字列を文字列を何らかの形で変数に分割することが目標であれば、here文字列を使用できます

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

それ以上のものがあると思いますが、もしなければこれはより良い選択肢です。


3
またはread a b dump <<< '1 2 3 4 5'
チョロバ14

mksh(cygwin)がbashと同じことをしていることに注意してください。
エマニュエル14

@マイケル・ホーマー良い説明!パイプラインのすべてのコマンドが独自のサブシェルで実行されることを説明できる別の例を見つけましたcat /etc/passwd | (read -r line ; echo $line)。ただし、次echo$lineパイプラインにないため、値は括弧(サブシェル)の間に存在するため、画面には何も表示されません。希望、それは誰かを助ける。
ユーリゴンチャルク

17

これはbashバグであり、振る舞いのPOSIX両方を許可するため、観察している不幸な矛盾につながります。bashksh

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

1
+1「lastpipe」情報をありがとう。遅れてごめんなさい
エマニュエル

1
問題lastpipeは、他のシェル(ダッシュなど)では機能しないことです。そのサブシェル内のすべてを実行しているこのポータブル短いを行うには方法は基本的にありません、見stackoverflow.com/questions/36268479/...
anarcat

1
@anarcatこれは正しいですが、ここで尋ねられた質問はbashについてでした。
jlliagre

@anarcat:これは、別の理由(PIPEステータス)でPOSIXを変更したいという要望があるため、将来変更される可能性があります。unix.stackexchange.com / questions / 476834 / ...他のシェルの変更は簡単ではなく、数か月かかりましたBourne Shell(bosh)のパーサーとインターピーターを書き換えて、最新のkshのより高速な動作を実装します。
18年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.