参数输入有效,但管道没有

时间:2012-11-11 12:30:15

标签: shell

我尝试创建一个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

提前致谢,

1 个答案:

答案 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