Bash While循环中逐行执行脚本仅运行一次的问题及解决方法
问题分析与解决:while循环仅执行一次的原因
你的脚本循环只跑一次的核心原因是:source 加载的quality-test.sh会继承当前shell的标准输入(也就是你用来读取parameters.txt的输入流)。如果quality-test.sh内部有任何读取标准输入的操作(哪怕是某些命令默认读取stdin的隐性行为),它会一次性把parameters.txt里剩下的所有行都读走,导致外层的read再也拿不到后续内容,循环直接终止。
下面是几种可行的解决方法:
方法1:给source的脚本重定向标准输入
让quality-test.sh的标准输入指向/dev/null,这样它就不会去读取parameters.txt的内容了:
BITRATE= QUALITY= while read -r BITRATE QUALITY; do source ./quality-test.sh -b "$BITRATE" -q "$QUALITY" < /dev/null done < parameters.txt
方法2:直接执行脚本而非source
既然单独运行./quality-test.sh完全正常,没必要用source。直接执行会启动子shell,不会占用当前shell的输入流,自然不会干扰循环的读取:
BITRATE= QUALITY= while read -r BITRATE QUALITY; do ./quality-test.sh -b "$BITRATE" -q "$QUALITY" done < parameters.txt
如果之前用source是为了共享环境变量,可以改成让quality-test.sh将结果输出到文件,或者通过其他方式传递数据,避免依赖当前shell环境。
方法3:用独立文件描述符保护输入流
把parameters.txt绑定到一个单独的文件描述符(比如3),让read从这个描述符读取内容,这样主stdin不会被内部脚本影响:
BITRATE= QUALITY= while read -r BITRATE QUALITY <&3; do source ./quality-test.sh -b "$BITRATE" -q "$QUALITY" done 3< parameters.txt
补充说明
你之前尝试的(...)子shell方式没用,是因为子shell默认继承父shell的stdin,只要quality-test.sh读stdin,还是会把剩下的行消耗掉。如果一定要用子shell,也要在子shell里给quality-test.sh重定向stdin到/dev/null才行。
内容的提问来源于stack exchange,提问作者dandan13
相关产品推荐
相关产品推荐

