shell在读取文件内容的同时读取控制台输入

有时候我们需要用while循环和read命令读取文件内容,那么这时候在循环中也需要从控制台读取输入怎么办呢?如下面这段代码:

#!/bin/bash
while read line
do
    echo $line
    echo "delete it? y/n"
    read key
    if [[ "$key" = "y" ]]; then
        sed -i "/$line/d" ./demo.txt
    fi
done < ./demo.txt

demo.txt:

hello
hi
tom

按行读取demo.txt中的内容,每读一行需要从控制台读取输入,输入y的话则删除此行内容。运行结果如下:

hello
delete it? y/n
tom
delete it? y/n

并没有从控制台读取输入,并且hi没有打印出来。从这里可以看出,read key这里把hi读入了key中,根据条件判断并不符合,所以代码继续执行下去了。

那么怎么解决呢?这里要用到文件描述符fd,代码修改如下:

#!/bin/bash
while read -u 2 line
do
    echo $line
    echo "delete it? y/n"
    read key
    if [[ "$key" = "y" ]]; then
        sed -i "/$line/d" ./demo.txt
    fi
done 2< ./demo.txt

运行结果:

$ ./test1.sh 
hello
delete it? y/n
y
hi
delete it? y/n
n
tom
delete it? y/n
n
$ cat demo.txt 
hi
tom

2< ./demo.txt表示demo.txt文件重定向到2号fd中

read -u 2这里-u参数表示从文件描述符中读入,该文件描述符可以是exec新开启的

下面的代码也是可行的:

#!/bin/bash
exec 2< ./demo.txt
while read -u 2 line
do
    echo $line
    echo "delete it? y/n"
    read key
    if [[ "$key" = "y" ]]; then
        sed -i "/$line/d" ./demo.txt
    fi
done