9

私は次の状況に悩まされています。

bashで、ループで1行ずつ実行したいファイルlist.txtがあります。list.txt の典型的な行にはスペースが含まれています。問題は、ループに「読み取り」コマンドが含まれていることです。このループは、perl などではなく、bash で記述したいと考えています。私はそれを行うことはできません:-(

通常、ファイルから行ごとに読み取るループを作成する方法は次のとおりです。

while read p; do
  echo $p
  echo "Hit enter for the next one."
  read x
done < list.txt

もちろん、「read x」はキーボードではなくlist.txtから読み取るため、これは機能しません。

そして、これも機能しません:

for i in `cat list.txt`; do
    echo $i
    echo "Hit enter for the next one."
  read x
done

list.txt の行にスペースが含まれているためです。

私は2つの解決策を提案していますが、どちらも悪臭を放っています:

1) list.txt を編集して、すべてのスペースを "THERE_SHOULD_BE_A_SPACE_HERE" にグローバルに置き換えることができます。次に、ループ内で sed のようなものを使用して、 THERE_SHOULD_BE_A_SPACE_HERE をスペースに置き換えると、すべて設定されます。list.txt のいずれかの行に THERE_SHOULD_BE_A_SPACE_HERE というフレーズが含まれていると失敗するという愚かな理由で、これは好きではありません (悪意のあるユーザーが私を混乱させる可能性があります)。

2) 標準入力で while ループを使用し、各ループで実際に新しい端末などを起動できます。これは、元のシェルで標準入力が関係する状況の影響を受けません。私はこれを試してみましたが、うまくいきましたが、醜いものでした.これらすべてをシェルスクリプトにまとめたいのですが、そのシェルスクリプトが新しいウィンドウをランダムに開くのは望ましくありません. 何がいいだろう、そしてどういうわけかこの質問への答えになるかもしれないのは、コマンドで新しいシェルを呼び出して、標準入力をフィードせずにコマンドをフィードする方法を理解できればよいのですが、取得できませんそれが機能します。たとえば、これは機能せず、その理由はよくわかりません:

while read p; do 
  bash -c "echo $p; echo ""Press enter for the next one.""; read x;"; 
done < list.txt

「read x」は、どういうわけか別のシェルにいるにもかかわらず、まだlist.txtから読み取っているように見えるため、この試みは失敗したようです。しかし、私はこれに近いかもしれないと感じています-誰が知っていますか.

ヘルプ!

4

3 に答える 3

15

別のファイル記述子として開く必要があります

while read p <&3; do
    echo "$p"
    echo 'Hit enter for the next one'
    read x
done 3< list.txt

更新: 以下のコメントでの長い議論は無視してください。質問やこの回答とは関係ありません。

于 2013-11-01T13:26:14.530 に答える
1

私はおそらくファイル内の行を数え、たとえばを使用してそれらのそれぞれを繰り返します。シード。while 条件を : に変更して標準入力から無限に読み取り、 ctrl+cwhile true;で読み取りを終了することもできます。

line=0 lines=$(sed -n '$=' in.file)
while [ $line -lt $lines ]
do
    let line++
    sed -n "${line}p" in.file
    echo "Hit enter for the next ${line} of ${lines}."
    read -s x
done

AWK は、このための優れたツールでもあります。入力を繰り返す簡単な方法は次のようになります。

awk '{ print  $0; printf "%s", "Hit enter for the next"; getline < "-" }' file
于 2014-03-12T21:14:40.150 に答える
0

別の方法として、デフォルトで tty にも接続されている stderr から読み取ることができます。次に、その仮定のテストも含まれます。

(
tty -s <& 2|| exit 1
while read -r line; do
    echo "$line"
    echo 'Hit enter'
    read x <& 2
done < file
)
于 2013-11-01T14:03:02.807 に答える