如何在Bash中添加数字列?
概述
本文探讨如何在bash shell中对数字列数据进行求和,探讨可用于此任务的bash工具并比较它们的运行速度。
使用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以执行计算。以下是一些方法。
使用Paste命令
首先,我们将查看“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命令的使用。然后,我们讨论了如何处理包含多列或单个带标题列的文件。