如何在 Bash 中添加一列数字?
概述
本文介绍如何在 Bash Shell 中对数据中的数字列进行求和,并介绍可用于此任务的 Bash 工具,并比较它们的速度。
使用 awk 工具
我们首先使用 awk (awk) 程序计算特定列中值的总和。
$ awk '{Total=Total+$1} END{print "Total is: " Total}' numbers.csv
Total is: 49471228
现在让我们使用"time"命令来看一下时间 -
$ time awk '{Total=Total+$1} END{print "Total is: " Total}' numbers.csv
Total is: 49471228
real 0m0.228s
user 0m0.141s
sys 0m0.047s
当文件包含多列时
我们已经了解了如何使用 awk 计算文件一行的总和。现在让我们看看如何计算文件多行的总和。
$ cat prices.csv Books,40 Bag,70 Dress,80 Box,10
此处,price.csv 文件包含两列。我们现在需要计算第二列值的总和。
$ awk -F "," '{Total=Total+$2} END{print "Total is: " Total}' prices.csv
Total is: 200
文件包含标题行的情况
有时,文本或 CSV 文件标题中还会包含一行包含列名的内容。我们将使用这些列名来帮助我们理解文件的内容。让我们编辑 prices.csv 文件并在顶部添加一个新行 -
$ cat prices.csv Item,Value Books,40 Bag,70 Dress,80 Box,10
当文件包含标题时,我们需要在文本处理之前删除标题。首先,我们在输入数据集中添加一个名为"title"的附加字段。然后,编写一个脚本,读取文件中的每条记录,并将新字段的值添加到总计中。最后,我们将打印结果。
$ awk -F "," 'NR!=1{Total=Total+$2} END{print "Total is: " Total}' prices.csv
Total is: 200
然后,我们将介绍一些其他将列中的数字相加的方法,并比较 awk 方法与它们的优缺点。
使用 Bash 循环进行迭代
Awk 是一个强大的工具,但我们也可以使用 for 循环来迭代列中的每个值。
使用 expr 命令
我们将进行一项实验,看看是否可以使用 expr 函数来计算 for 循环内数字的总和。
$ time (sum=0;for number in `cat numbers.csv`; do sum=`expr $sum + $number`; done; echo "Total is: $sum") Total is: 49471228 real 212m48.418s user 7m19.375s sys 145m48.203s
使用算术扩展
由于使用"expand"没有太大帮助,我们将尝试另一种使用算术表达式的方法 -
$ time (sum=0;for number in `cat numbers.csv`; do sum=$((sum+number)); done; echo "Total is: $sum") Total is: 49471228 real 0m1.961s user 0m1.813s sys 0m0.125s
为了计算总数,我们将使用算术运算符。与 expr 运算符不同,$(...) 运算符可以处理整数和浮点数。
使用 bc 命令添加值
bc 命令对由多行组成的表达式执行计算。因此,我们必须将数字连接成一行,并用加法运算符分隔它们。然后将结果字符串传递给 bc 执行计算。以下是几种执行此操作的方法。
使用粘贴命令
首先,我们将了解"PASET"命令,它将数据集的前十个数字排列在一行上。
$ cat numbers.csv| head -10 | paste -sd+ - 2+44+6+15+23+0+15+88+82+1
选项 -s 确保 paste 命令将每个条目打印在各自的行上。我们还使用了 +d 选项在每个条目之间添加"+"符号作为分隔符。
现在我们已经了解了基础知识,接下来让我们继续向 bc 命令提供输入。
$ time echo "Total is: $(cat numbers.csv | paste -sd+ - | bc)" Total is: 49471228 real 0m0.244s user 0m0.203s sys 0m0.063s
使用 tr 命令
我们再次使用 tr(音译)函数,从现有字符串创建新字符串。
$ cat numbers.csv | head -10 |tr "
" "+" 2+44+6+15+23+0+15+88+82+1+
我们在字符串开头添加了一个额外的零,以便可以使用 bc 命令执行加法运算。但是,请注意字符串末尾的额外"+"。为了解决这个问题,我们可以在行尾添加另一个零。
$ cat numbers.csv | head -10 |tr "
" "+" ; echo "0" 2+44+6+15+23+0+15+88+82+1+0
让我们将上一个命令的结果重定向到 bc 命令。
$ time ((cat numbers.csv | tr "
" "+" ; echo "0") | bc) 49471228 real 0m0.217s user 0m0.203s sys 0m0.031s
结合使用 tr 和 bc 命令比使用 awk 运行速度更快。
使用 sed 命令
我们最终将使用 sed 命令来生成序列。
$ cat numbers.csv | head -10 | sed -z 's#
#+#g' 2+44+6+15+23+0+15+88+82+1+
我们使用 sed 命令的搜索和替换选项将换行符 ("
") 替换为加号 ("+"),并在末尾打印零以处理多余的加号。
$ time ((cat numbers.csv | sed -z 's#
#+#g' ; echo "0") | bc) 49471228 real 0m0.343s user 0m0.281s sys 0m0.109s
要更改换行符的含义,请使用"–z"选项。现在,换行符不再被解释为每个输入的开头,而是被视为空字符。因此,如果我们将换行符替换为加号 (+),则会得到以下输出 -
如果您要处理大量文本,可能需要使用 sed 而不是 tr。
结论
我们研究了在 bash shell 中对多列数字进行加法运算的不同方法。
我们首先讨论了 awk 命令的用法。然后,我们讨论了如何处理包含多列或单列(带标题)的文件。
相关文章
有用资源
linux 参考教程 - 该教程包含有关 linux 的更多信息:https://www.cainiaomax.com/linux/

