3

Using bash I want to read over a list of lines and ask the user if the script should process each line as it is read. Since both the lines and the user's response come from stdin how does one coordinate the file handles? After much searching and trial & error I came up with the example

exec 4<&0
seq 1 10 | while read number
do
    read -u 4 -p "$number?" confirmation
    echo "$number $confirmation"
done

Here we are using exec to reopen stdin on file handle 4, reading the sequence of numbers from the piped stdin, and getting the user's response on file handle 4. This seems like too much work. Is this the correct way of solving this problem? If not, what is the better way? Thanks.

4

3 に答える 3

2

readより抽象的な標準入力の代わりに、ターミナルから入力を強制的に取得することができます。

while read number
do
    < /dev/tty read -p "$number?" confirmation
    echo "$number $confirmation"
done

欠点は、受け入れを自動化できないことです(yesたとえば、に接続されたパイプから読み取ることによって)。

于 2012-08-13T13:17:44.640 に答える
1

はい、追加のファイル記述子を使用することは、この問題を解決する正しい方法です。パイプは、あるコマンドの標準出力 (ファイル記述子 1) を別のコマンドの標準入力 (ファイル記述子 1) にのみ接続できます。したがって、コマンドの出力を解析しているときに、他のソースから入力を取得する必要がある場合は、その他のソースをファイル名またはファイル記述子で指定する必要があります。

これを少し違った方法で書き、リダイレクトをループに対してローカルにしますが、大したことではありません。

seq 1 10 | while read number
do
    read -u 4 -p "$number?" confirmation
    echo "$number $confirmation"
done 4<&0

bash 以外のシェルでは、-uへのオプションがないread場合、リダイレクトを使用できます。

printf "%s? " "$number"; read confirmation <&4

ファイル記述子の再割り当てを使用する他の例に興味があるかもしれません。

chepner で指摘されている別の方法は、プログラムが実行されている端末である名前付きファイルから読み取ること/dev/ttyです。これにより、スクリプトが単純になりますが、確認データを簡単にフィードできないという欠点があります。スクリプトを手動で。

于 2012-08-16T19:01:20.973 に答える
0

アプリケーションの場合、killmatching、2つのパスが完全に正しい方法です。

  • 最初のパスでは、一致するすべてのプロセスを配列に読み込むことができます。数は少なく(通常は数十、最大で数万)、効率の問題はありません。コードは次のようになります

    set -A candidates
    ps | grep | while read thing do candidates+=("$thing"); done
    

    (構文の詳細が間違っている可能性があります。私のbashは錆びています。)

  • candidates2番目のパスは配列をループし、相互作用を行います。

また、プラットフォームで利用できる場合は、を調べてくださいpgrep。これは理想的ではありませんが、いくつかのフォークを節約できる可能性があります。これは、世界中のすべての配列ルックアップよりもコストがかかります。

于 2012-08-13T01:11:18.757 に答える