Bash while循环,带有done < $1

3

我对done < $1的符号有点困惑。

我正在尝试编写一个名为“sumnums”的程序,它读取名为“nums”的文件,其中包含一些数字行。然后,它应该打印数字行,接着是所有数字的总和。

目前我的代码如下:

#!/bin/bash
sum=0;
while read myline
do  
  echo "Before for; Current line: \"$myline\""
done
for i in $myline; do  
  sum=$(expr $sum + $i)
done < $1    
echo "Total sum is: $sum"

程序在正确输出nums列表后,输出./sumnums: line 10: $1: ambiguous redirect,然后输出Total sum is: 0。看起来它没有进行加法计算。请问如何重新排列这些代码行以修复程序并消除"ambiguous redirect"的错误?


你是如何调用你的脚本的?可以使用 ./sumnum nums 来调用,或者将 done < $1 改为 done < nums - codeforester
cat nums | ./sumnums - themightyscot
脚本需要文件作为参数。 - karakfa
@themightyscot,顺便说一下,通常情况下,“./sumnums <nums”比“cat nums | ./sumnums”更有效率。在前者中,您直接将文件“nums”提供给了“sumnums”;而在后者中,您强制“sumnums”读取第二个程序(“cat”)的输出,并仅将该独立软件访问输入文件。 - Charles Duffy
话虽如此,如果您实际上没有运行 ./sumnums nums,并将 nums 传递给 $1,那么 $1 中就没有文件名,因此 <"$1" 根本没有意义。 - Charles Duffy
显示剩余3条评论
2个回答

4
假设您的文件名位于$1中(也就是说,您的脚本是通过./yourscript nums调用的):
#!/bin/bash

[[ $1 ]] || set -- nums  ## use $1 if already set; otherwise, override with "nums"

sum=0
while read -r i; do      ## read from stdin (which is redirected by < for this loop)
  sum=$(( sum + i ))     ## ...treat what we read as a number, and add it to our sum
done <"$1"               ## with stdin reading from $1 for this loop
echo "Total sum is: $sum"

如果$1中不包含你的文件名,则需要使用包含文件名的其他内容,或者直接将实际的文件名硬编码。
注:
  • <"$1"应用于while read循环。这是必需的,因为在此上下文中,read是实际从文件中消耗内容的命令。将标准输入重定向到for循环可能有意义,但仅当该循环内部有东西正在从标准输入读取时。
  • $(( ))是现代POSIX sh算术语法。 expr是遗留的语法,不要使用它。

0

awk 来拯救!

awk '{for(i=1;i<=NF;i++) sum+=$i} END{print "Total sum is: " sum}' file

bash 不是这个任务的正确工具。


1
“done <” 的文档在哪里可以找到?在Bash中,“<”的含义是什么?它是否有一个像“redirect”这样的名称,可以在其文档中找到? - Jacob Wegelin
1
@JacobWegelin 如果我知道一个简单的解释,我会提供它,但我也在摸索中。这里有一个文档链接。找到这一行:done < <(route -n)

^ ^ 第一个<是重定向,第二个是进程替换。

- Connor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接