我尝试创建一个shell脚本,它将给定的数字相加。如果没有给定参数,则它会尝试读取管道输出,但是我收到错误。
#!/bin/sh
sum=0
if [ $# -eq 0 ]
then
while read data
do
sum=`expr $sum + $data`
done
else
for (( i = 1 ; i <= $#; i++ ))
do
sum=`expr $sum + ${!i}`
done
fi
echo $sum
这有效:sum 10 12 13
但是这个不是:echo 10 12 13| sum
提前致谢,
答案 0 :(得分:3)
你走了(假设是bash
,而不是sh
):
#!/bin/bash
sum=0
if (( $# == 0 )); then
# Read line by line
# But each line might consist of separate numbers to be added
# So read each line as an array!
while read -a data; do
# Now data is an array... but if empty, continue
(( ${#data[@]} )) || continue
# Convert this array into a string s, with elements separated by a +
printf -v s "%s+" ${data[@]}
# Append 0 to s (observe that s ended with a +)
s="${s}0"
# Add these numbers to sum
(( sum += s ))
done
else
# If elements come from argument line, do the same!
printf -v s "%s+" $@
# Append 0 to s (observe that s ended with a +)
s="${s}0"
# Add these numbers to obtain sum
(( sum = s ))
fi
echo $sum
你可以这样调用它:
$ echo 10 12 13 | ./sum
35
$ ./sum 10 12 13
35
$ # With several lines and possibly empty lines:
$ { echo 10 12 13; echo; echo 42 22; } | ./sum
99
希望这有帮助!
编辑。您可能也有兴趣学习有关IFS
的精彩内容。我注意到人们往往会在@
中混淆*
和bash
。如果您不知道我在说什么,那么您应该使用@
代替*
,也可以使用数组下标!在bash
手册中,您会发现,当双引号时,$*
(或${array[*]}
)会扩展到数组的所有元素,并以{{的值分隔1}} 即可。这在我们的案例中很有用:
IFS
Gniourf现在退出教师模式。 #!/bin/bash
sum=0
if (( $# == 0 )); then
# Read line by line
# But each line might consist of separate numbers to be added
# So read each line as an array!
while read -a data; do
# Now data is an array... but if empty, continue
(( ${#data[@]} )) || continue
# Setting IFS=+ (just for the sum) will yield exactly what I want!
IFS=+ sum=$(( sum + ${data[*]} ))
done
else
# If elements come from argument line, do the same!
# Setting IFS=+ (just for the sum) will yield exactly what I want!
IFS=+ sum=$(( $* ))
fi
echo $sum