shell - while 读取循环内读取 key 失败

标签 shell stdin io-redirection

这是我的脚本,用于检测按键按下:

#!/bin/bash
echo "Reading keys."
while [ "x$keypress" = "x" ]; do
  read -n 1 -t 1 -s keypress
  printf "."
done
printf "\n"
echo "Pressed key: "$keypress

这似乎工作正常(例如在一段时间后按“q”键):

$ ./InputKey.sh
Reading keys.
.............................................
Pressed key: q

但是如果我把它放在一个循环中,它会读取我的 File.txt并等待每一行的键:

#!/bin/bash
MyList=File.txt
while IFS=, read -ra ListLine
do
    echo "Processing line: "$ListLine
    echo "Press [S] to count as Secret or [P] to count as Public."
  while [ "x$keypress" = "x" ]; do
        read -n 1 -t 1 -s keypress
    printf "."
    done
    printf "\n"
    echo "Pressed key: "$keypress
done < "$MyList"

程序根本不等待按键,这是奇怪的结果:

$ ./prueba07.sh
Processing line: d:\Temp
Press [S] to count as Secret or [P] to count as Public.
.
Pressed key: c
Processing line: :\Temp
Press [S] to count as Secret or [P] to count as Public.

Pressed key: c
Processing line: e:\Temp
Press [S] to count as Secret or [P] to count as Public.

Pressed key: c
Processing line:
Press [S] to count as Secret or [P] to count as Public.

Pressed key: c

这是File.txt内容:

d:\Temp
c:\Temp
e:\Temp 

我在某处读到问题来自 <"$MyList"重定向器,消耗所有stdin

所以,我找到了this thread并添加&3重定向器:

#!/bin/bash
MyList=File.txt
while IFS=, read -ra ListLine <&3
do
    echo "Processing line: "$ListLine
    echo "Press [S] to count as Secret or [P] to count as Public."
  while [ "x$keypress" = "x" ]; do
        read -n 1 -t 1 -s keypress
    printf "."
    done
    printf "\n"
    echo "Pressed key: "$keypress
done 3< "$MyList"

现在程序等待按下一个键。但其余部分会自动重复(例如仅按 p 一次):

$ ./prueba07.sh
Processing line: d:\Temp
Press [S] to count as Secret or [P] to count as Public.
..
Pressed key: p
Processing line: c:\Temp
Press [S] to count as Secret or [P] to count as Public.

Pressed key: p
Processing line: e:\Temp
Press [S] to count as Secret or [P] to count as Public.

Pressed key: p
Processing line:
Press [S] to count as Secret or [P] to count as Public.

Pressed key: p

这样的问题如何解决呢? 谢谢你。

EDIT-01:测试了读取关键行的此更改,但没有结果:

read -n 1 -t 1 -s keypress </dev/tty

摘自this other线程。

EDIT-02:在 Ubuntu Desktop v12 和 CygWin (Windows 7) 上测试。

EDIT-03:以下答案是正确的。我为脚本选择的最终更改是(最后只有一行):

#!/bin/bash
MyList=File.txt
while IFS=, read -ra ListLine <&3
do
    echo "Processing line: "$ListLine
    echo "Press [S] to count as Secret or [P] to count as Public."
  while [ "x$keypress" = "x" ]; do
        read -n 1 -t 1 -s keypress
    printf "."
    done
    printf "\n"
    echo "Pressed key: "$keypress
    unset keypress
done 3< "$MyList"

最佳答案

您可以从不同的文件描述符读取,并重构内部循环

while IFS=, read -r -u 3 -a ListLine
do
  echo 'Processing line:' "$ListLine"
  echo 'Press [S] to count as Secret or [P] to count as Public.'
  until read -n 1 -t 1 -s keypress
  do
    printf .
  done
  echo
  echo 'Pressed key:' $keypress
done 3< File.txt

Does bash support doing a read nested within a read loop?

关于shell - while 读取循环内读取 key 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27350028/

相关文章:

shell - 有没有办法在运行脚本时自动输入?

c++ - 支持管道(一个有用的 Hello World)

hadoop - 使用标准输出重定向创建临时文件以加载到 Hive 表中

shell - 如何像 log4j 那样将输出通过管道传输到 shell 中的旋转日志文件?

linux - 如何在bash脚本中串行运行sql脚本?

function - 如何将 shell 函数从一个文件导入到另一个文件中?

bash - 如何测试 rm 的 GNU 或 BSD 版本?

c++ - 如何使用 Qt 5.7 初始化 stdout stdin

c++ - gdb 在 Emacs 中不接受 stdin 重定向

python - 重定向当前正在运行的 python 进程的 stdout