2014-09-10 40 views
0

我刚刚开始在我的学校编程shell脚本,我遇到了一些问题,我无法找到答案。为什么在bash脚本中,算术表达式的改变会改变ct​​rl-d的行为?

我有一个学校的任务是制作一个shell脚本,用户应该键入一个数字+输入并重复此操作,直到用户键入ctrl + d,然后该程序应该回显总和,程序应该结束。

这是我写的脚本。

sum=0 
while [ true ] 
do 
    read number 
    sum=$(($sum+$number)) 
done 

function finish { 
    echo "Sum: $sum" 
} 

trap finish exit 

跑在我的终端脚本,它看起来像这样:

4 
5 
summer.sh: line 5: 9+: syntax error: operand expected (error token is "+") 
Sum: 9 

我读How can I add numbers in a bash script,以为我所用的算术表达式正确的(它甚至还可以显示正确的总和),但无论如何我尝试另一个来自同一问题的建议。我改成:

sum=$((sum+number)) 

现在我没有得到语法错误。但是我不能通过键入ctrl-d来终止程序。 现在运行代码示例:

4 
5 
^D 
^C 

发生了什么事?为什么脚本中算术表达式的改变会影响ctrl-d的行为?

回答

0

有一对夫妇在你的脚本的问题:

你从来没有检查read结果。 按Ctrl + d将使read为1的错误代码终止,所以你应该检查:

read number || break 

否则,bash将永远不会退出循环。

然后,trap应位于脚本的顶部(这意味着您也必须移动function)。 BASH逐行读取脚本。它不展望未来。所以,你的非常复杂的代码(function高达exit)是完全一样的:

echo "Sum: $sum" 

移动function顶端尽管$sum未在规定的时间其实应该工作时该函数解析,因为BASH当它被调用时将再次读取该函数的主体。那时,sum应该存在并且具有正确的值。

+0

“陷阱”的定位是一个好点,但在这种情况下并不重要。由于'trap'上面没有任何东西会退出脚本,所以在脚本退出正常操作之前它将被执行。这里的主要问题是'read'返回问题。由于数字上下文错误,第一个脚本退出。第二个并不是因为未设置的变量在数值上下文中计算为0(但显式变量扩展显然扩展为空的空字符串,这是我不知道的)。 – 2014-09-10 09:51:04

+0

谢谢!我会尽力修复它! Reisner: “第一个脚本因为数字上下文错误而存在” 不,它在ctrl + d键入时退出。我可以使用更多的输入来运行程序,并且在键入ctrl-d之前它不会退出。编辑: 加入||打破固定它! :) – user3065567 2014-09-10 11:23:18

+0

@ user3065567是的,当你点击ctrl-d时,你不会读取任何数据,所以你的变量是空的,导致数字上下文中的解析错误导致脚本退出。在数值上下文中切换到隐式变量扩展(删除'$'),错误消失,因为“空”变量现在扩展为“0”,因此您得到一个有效的数值表达式,没有错误,结束。我可能会将这个解释扩展为一个答案,以便更充分地解释和演示。 – 2014-09-10 12:21:22

0

该脚本应该说明shell运行的问题以及模拟脚本固定版本的作用。

#!/bin/bash 

sum=0 
while true 
do 
    read -p 'Number? ' number 
    echo "number:$number:" 
    echo "\$(($sum+$number))" 
    echo "\$(($sum+${number:-0}))" 
done 

$ ./explain.sh 
Number? 5 
number:5: 
$((0+5)) 
$((0+5)) 
Number? 3 
number:3: 
$((0+3)) 
$((0+3)) 
# At this prompt I just hit enter 
Number? 
number:: 
$((0+)) 
$((0+0)) 
# At this prompt I hit ctrl-d 
Number? number:: 
$((0+)) 
$((0+0)) 

为未定义的变量置换由零在手册页解释:

壳牌变量允许作为操作数;在评估表达式之前执行参数扩展 。在 表达式中,shell变量也可以在不使用参数扩展语法的情况下通过名称 引用。如果不使用参数扩展语法,则在名称为 时引用的空值或未设置的shell变量 的值为0。

相关问题