如何在 Bash 中添加一列数字?

linuxopen sourceoperating system

概述

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


相关文章


有用资源