3

我有一行数字,我希望能够一个一个地处理它们。例如。

3829 4837 3729 2874 3827 

我希望能够得到总和,最大的数字,任何东西。但我不知道如何让每个号码来处理它。我会 REAAAAALLLLLLLLLY 喜欢坚持使用纯 bash,我不介意 bash 中复杂的解决方案。但如果 awk 是绝对必要的,我会使用它。我不想使用 sed。

我想我可以做类似的事情:

max= cut -d" " -f1
in line L cut -d" " -f$(loop index) 
#check for max

我很困惑。

编辑:感谢您的回答,我看到了一些我在 bash 中从未见过的新事物,我已准备好进一步探索它们。我收到了我想要的信息,甚至更多!:)

4

3 回答 3

3

如果要一个一个处理进程号,请利用shell 分词

numbers="3829 4837 3729 2874 3827"
 for n in $numbers; do
     # do something with "$n"
done

SUM

numbers="3829 4837 3729 2874 3827"
echo $((${numbers// /+}))

或者

numbers="3829 4837 3729 2874 3827"
for n in $numbers; do
     ((sum+=n))
done

echo $sum

LARGEST

numbers="3829 4837 3729 2874 3827"
for n in $numbers; do
     ((max<n)) && max=$n
done

echo $max

或者,如果您想要一个SUM带有一些 shell 技巧的全局变量:

$ tr ' ' '+' <<< '3829 4837 3729 2874 3827' | bc                                 
19096 

或者

$ awk '{$1=$1; print}' OFS=+ <<< '3829 4837 3729 2874 3827' | bc
19096

或者

$ echo  '3829 4837 3729 2874 3827' |
    awk '{for (i=1; i<=NF; i++) c+=$i} {print c}'
19096
于 2013-03-21T19:04:04.080 回答
3

如果您在字符串中有数字列表,则按以下方式处理它们是拆分和迭代的最安全方法(同时避免全局扩展或其他副作用):

max=0
read -r -a number_array <<<"$numbers"
for number in "${number_array[@]}"; do
  if (( number > max )) ; then
    max=number
  fi
done    

如果您正在读取文件,则需要进行简单的修改(有关读取文件的最佳做法,请参阅http://mywiki.wooledge.org/BashFAQ/001 ):

max=0
while read -r -a numbers; do
  for number in "${numbers[@]}"; do
    if (( number > max )) ; then
      max=number
    fi
  done
done <input-file

如果你的分隔符是别的东西,你可以适当地设置 IFS。例如,如果用逗号分隔:

while IFS=, read -r -a numbers; do

请注意,当您的值确实仅限于数字时,此处给出的最佳实践并不重要。但是,如果您*的输入数据中有 a ,并且您只需运行

for number in $numbers; do

然后字符串*中的$numbers将替换为当前目录中的文件列表。不要那样做。

最后一点——bash 没有对浮点数学的内置支持。如果您需要浮点数学,请参阅http://mywiki.wooledge.org/BashFAQ/022

于 2013-03-21T19:14:41.603 回答
2

这里有几种方法可以将一串单词拆分成一个可以迭代的结构:

使用位置参数

numbers="3829 4837 3729 2874 3827"
set -- $numbers
sum=0
for n in "$@"; do
    # do something with $n
    (( sum += n ))
done
average=$(( sum / $# ))   # integer division only

使用实际数组

numbers="3829 4837 3729 2874 3827"
nums=( $numbers )
sum=0
for n in "${nums[@]}"; do
    # do something with $n
    (( sum += n ))
done
average=$(( sum / ${#nums[@]} ))   # integer division only
于 2013-03-21T20:02:51.540 回答