![在 bash 单行代码中使用 Ctrl-C 中断 while 循环后运行命令?](https://linux22.com/image/218600/%E5%9C%A8%20bash%20%E5%8D%95%E8%A1%8C%E4%BB%A3%E7%A0%81%E4%B8%AD%E4%BD%BF%E7%94%A8%20Ctrl-C%20%E4%B8%AD%E6%96%AD%20while%20%E5%BE%AA%E7%8E%AF%E5%90%8E%E8%BF%90%E8%A1%8C%E5%91%BD%E4%BB%A4%EF%BC%9F.png)
在下面的一行中,我运行一个“无限”while 循环来打印一些数字:
$ bash -c 'trap stopit SIGINT; run=1; stopit() { run=0; }; while [ $run ]; do for i in {0..4}; do v=$(($i*50)); d=$(for ((k=0;k<=(5+$i);k++)); do echo -n $(($v*(($k+$i)%2))),; done); d=${d%?}; c=$(echo numbers $d); echo $c; sleep 0.1; done; done ; echo Done'
numbers 0,0,0,0,0,0
numbers 50,0,50,0,50,0,50
numbers 0,100,0,100,0,100,0,100
numbers 150,0,150,0,150,0,150,0,150
numbers 0,200,0,200,0,200,0,200,0,200
numbers 0,0,0,0,0,0
numbers 50,0,50,0,50,0,50
numbers 0,100,0,100,0,100,0,100
...
...“扩展”脚本是:
trap stopit SIGINT;
run=1;
stopit() {
run=0;
};
while [ $run ]; do
for i in {0..4}; do
v=$(($i*50));
d=$(for ((k=0;k<=(5+$i);k++)); do echo -n $(($v*(($k+$i)%2))),; done);
d=${d%?}; # cut final comma
c=$(echo numbers $d);
echo $c;
sleep 0.1;
done;
done ;
echo Done
这个想法是while
循环“永远”运行并打印(正在运行的任务),一旦你感到无聊,你可以通过按 Ctrl-C 来停止它。但是,我想要的是打印一条消息后Ctrl-C 中断了 while 循环 - 在上面的示例中,这就是echo Done
命令。
在上面的例子中,我希望 Ctrl-C 将变量设置run
为 0,从而使循环“干净地”退出,然后打印命令并退出。不幸的是,当我按 Ctrl-C 时没有任何反应,也就是说,循环继续进行,然后我必须明确地执行kill
它。
如何使上述脚本/一行退出 Ctrl-C 上的 while 循环,并打印最终消息?
答案1
好吧,明白了,我想:
$ bash -c 'trap stopit SIGINT; stopit() { echo Done; exit; }; while [ 1 ]; do for i in {0..4}; do v=$(($i*50)); d=$(for ((k=0;k<=(5+$i);k++)); do echo -n $(($v*(($k+$i)%2))),; done); d=${d%?}; c=$(echo numbers $d); echo $c; sleep 0.1; done; done ;'
numbers 0,0,0,0,0,0
numbers 50,0,50,0,50,0,50
numbers 0,100,0,100,0,100,0,100
numbers 150,0,150,0,150,0,150,0,150
numbers 0,200,0,200,0,200,0,200,0,200
numbers 0,0,0,0,0,0
numbers 50,0,50,0,50,0,50
numbers 0,100,0,100,0,100,0,100
numbers 150,0,150,0,150,0,150,0,150
numbers 0,200,0,200,0,200,0,200,0,200
numbers 0,0,0,0,0,0
Done
基本上,“更改全局变量以干净地退出”的概念将不起作用,因为函数中的变量bash
始终是本地范围,并且“隐藏”全局变量,请参阅:
所以读完之后
...事实证明,最好将最终命令(“echo Done”)移动到陷阱处理程序中,然后在它之后,从陷阱处理程序中exit
直接发出(不要担心“干净地退出 while 循环以之后打印”的事情)