read 只会读取一行,而cat 基本上会读取并回显到文件末尾。
对于read 版本,您最好在获得OK 之前暂停阅读(并存储任何包含大量数字的行)。
我想你会发现不是关闭 3 号文件句柄会阻止事情 - 更有可能是 cat 将继续读取/回显直到结束没有发生的文件事件。
如果您只是输入以下内容,您就可以确定:
echo XYZZY
紧接在结束 exec 语句之前。如果它还在cat 中,您将永远看不到它。
所以,使用循环的read 版本可能也可以解决这个问题。
例如,您可以使用read 在标准输入中执行此操作:
#!/bin/bash
NUM=
while true ; do
read -p "> " -t 10 -r RESP <&0
if [[ $? -ge 128 ]] ; then RESP=OK ; fi
echo "Entered: $RESP"
if [[ $RESP = OK ]] ; then break ; fi
if [[ $RESP =~ ^[0-9] ]] ; then NUM=$RESP ; fi
done
echo "Finished, numerics were: '$NUM'"
它使用read 的超时功能来检测是否没有更多输入(将输入设置为OK 以强制循环退出)。如果您在此之前确实获得了OK,无论如何它都会正常退出,超时只是为了迎合调制解调器无法按预期响应的可能性。
该数字最初设置为空,但会被“调制解调器”中以数字开头的任何行覆盖。
两个示例运行,有和没有来自“调制解调器”的OK 响应:
pax> ./testprog.sh
> hello
Entered: hello
> 12345
Entered: 12345
> OK
Entered: OK
Finished, numerics were: '12345'
pax> ./testprog.sh
> hello
Entered: hello
> now we wait 10 secs
Entered: now we wait 10 secs
> Entered: OK
Finished, numerics were: ''
将它转换为与您的调制解调器设备类似的东西并不难(read <&3 或 read -u3 都可以正常工作)。
这基本上会转化为您的环境:
exec 3<>/dev/ttyUSB3
echo -e "AT+CGSN\n" >&3
NUM=
while true ; do
read -t 10 -r RESP <&3
if [[ $? -ge 128 ]] ; then RESP=OK ; fi
echo "Entered: $RESP"
if [[ $RESP = OK ]] ; then break ; fi
if [[ $RESP =~ ^[0-9] ]] ; then NUM=$RESP ; fi
done
echo "Finished, numerics were: '$NUM'"
exec 3<&-
exec 3>&-
现在我还没有测试过,因为我没有连接调制解调器(已经使用宽带很长一段时间了),但它应该 接近你需要什么,如果不准确的话。