如何在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命令的使用。然后,我们讨论了如何处理包含多列或单个带标题列的文件。

更新于:2023年1月3日

浏览量 1K+

启动您的职业生涯

完成课程获得认证

开始学习
广告