如何在Bash中计算整数列表的和

如何在Bash中计算整数列表的和,bash,shell,sum,integer,Bash,Shell,Sum,Integer,我有一个关于bashshell中计算来自文件的整数总和的问题。我要求和的整数位于最后一个字段中,每行有awk($NF) 从技术上讲,下面是我的Bash命令: sum=0 for i in $(grep 'number_vars' file.txt | sed 's/_//g;s/,/./g;s/\.00//g' | awk '{print $NF}'); do sum=$((sum+i)); done 不幸的是,最后一个命令产生了一个错误:语法错误:算术运算符无效,我不明白为什么 因此,我继续

我有一个关于bashshell中计算来自文件的整数总和的问题。我要求和的整数位于最后一个字段中,每行有awk($NF)

从技术上讲,下面是我的Bash命令:

sum=0
for i in $(grep 'number_vars' file.txt | sed 's/_//g;s/,/./g;s/\.00//g' | awk '{print $NF}'); do sum=$((sum+i)); done
不幸的是,最后一个命令产生了一个错误:
语法错误:算术运算符无效
,我不明白为什么

因此,我继续尝试通过将所有整数存储到文件
temp.dat
中来修复此错误,如下所示:

for i in $(grep 'numbers_vars' file.txt | sed 's/_//g;s/,/./g;s/\.00//g' | awk '{print $NF}'); do echo $i >> temp.dat; done
我为
temp.dat
获取以下内容:

$ cat temp.dat 
    500
    110
    300
    110
    110
    110
    1500
    110
    1500
    110
    110
    110
    3000
    110
    110
    110
    3000
    3000
    110
    110
那么,如果我这样做:

sum=0
for i in $(cat temp.dat); do sum=$((sum+i)); done
始终存在相同的错误:
语法错误:算术运算符无效

我也尝试过:
sum=$($sum+$I))
但没有成功

我不知道现在该怎么办

更新1:WILSON对应于姓氏:

$ LC_ALL=C cat -vt file_in.txt | grep WILSON 

WILSON PETER "^I^I500,00^M
WILSON PETER MR WILSON J MR WILSON PETER "^I^I110,00^M
WILSON PETER "^I^I300,00^M
MR WILSON CHRISTOPHE VIREMENT S ^M
WILSON PETER MR WILSON J MR WILSON PETER "^I^I110,00^M
MR WILSON CHRISTOPHE VIREMENT S ^M
WILSON PETER MR WILSON J MR WILSON PETER "^I^I110,00^M
WILSON PETER MR WILSON J MR WILSON PETER "^I^I110,00^M
WILSON PETER "^I^I1_500,00^M
WILSON PETER MR WILSON J MR WILSON PETER "^I^I110,00^M
WILSON PETER "^I^I1_500,00^M
WILSON PETER MR WILSON J MR WILSON PETER "^I^I110,00^M
WILSON PETER MR WILSON J MR WILSON PETER "^I^I110,00^M
WILSON PETER MR WILSON J MR WILSON PETER "^I^I110,00^M
WILSON PETER "^I^I3_000,00^M
...
更新2:SOLUTION我找到了如何获得格式良好的文本文件(.txt),即每行对应于初始Excel表的一行的文件。我必须得出结论,在我的MacOS Catalina上导出Excel 2019工具真是胡说八道:我通过编辑生成的文本文件意识到,所有内容都是混合的,即一行可能是Excel表格整行的一部分等等。。。最后,我不能用这种糟糕的格式做任何事情

解决方案:如果它能帮助那些想用bash函数快速处理Excel表格的人,请参见下面我所做的

1) First export the Excel table to a PDF file
2) Open PDF file with Acrobat and export it to "raw text"
3) Then, I can check with `vim` is well formatted, i.e "a line in Excel table" equal to "one line in text file
4) After this checking, you can apply the different solutions suggested by all the people who helped me to compute the sum of the desired column.
For example, by following the procedure above from 1) to 4), I have just to do : 

awk '{sum+=$2}END{print sum}' file.txt
最后,不要忘记这不是关于我的终端命令的问题,它们是正确的,而是关于Excel生成的错误文本文件的问题


因此,我找到了通过使用中介工具(Acrobat)来规避这个问题的方法。我同意这有点棘手,但使用Excel唯一的文本导出工具,我并没有做得更好。

我无法查看原始输入数据,但您应该能够在awk中完成这一切:

sum=$(awk'
{
gsub(/,+/,“,$NF);
gsub(/[^0-9.]+/,“”,$NF);
总和+=$NF;
}结束{
打印金额;
}
'file.txt)
(如果需要,可以折叠空白并将其展开到一条线上。)

这将完全用awk汇编逻辑,包括加法,只打印最终的和

注意,awk可以处理小数,所以我保留了它们的完整性。POSIX shell和bash不能处理小数。你的
s/\.00//g
对我来说很奇怪,因为它会把
5.004
变成
54
,但也许你的精度永远不会超过百分之一?这个精度总是
.00

逐行解释AWK逻辑:

  • 无条件(始终为每一行运行):
    • 用点替换所有连续逗号(仅最后一个字段)
    • 删除既不是数字也不是点的所有字符(仅最后一个字段)
      → 这将解决您对不可见字符的任何问题
    • 将该值添加到
      sum
      变量(自动初始化为零)
  • 读取所有行后:
    • 打印那笔金额
如果您需要将最终值设置为整数,例如,因为您将进行进一步的bash算术或数字比较,请将该
print
行替换为
printf“%d”,sum
(truncate)或
printf“%.0f”,sum
(舍入)


如果这不能解决您的问题,我希望使用
hd file.txt

查看您输入的十六进制转储。我无法查看原始输入数据,但您应该能够在awk中完成这一切:

sum=$(awk'
{
gsub(/,+/,“,$NF);
gsub(/[^0-9.]+/,“”,$NF);
总和+=$NF;
}结束{
打印金额;
}
'file.txt)
(如果需要,可以折叠空白并将其展开到一条线上。)

这将完全用awk汇编逻辑,包括加法,只打印最终的和

注意,awk可以处理小数,所以我保留了它们的完整性。POSIX shell和bash不能处理小数。你的
s/\.00//g
对我来说很奇怪,因为它会把
5.004
变成
54
,但也许你的精度永远不会超过百分之一?这个精度总是
.00

逐行解释AWK逻辑:

  • 无条件(始终为每一行运行):
    • 用点替换所有连续逗号(仅最后一个字段)
    • 删除既不是数字也不是点的所有字符(仅最后一个字段)
      → 这将解决您对不可见字符的任何问题
    • 将该值添加到
      sum
      变量(自动初始化为零)
  • 读取所有行后:
    • 打印那笔金额
如果您需要将最终值设置为整数,例如,因为您将进行进一步的bash算术或数字比较,请将该
print
行替换为
printf“%d”,sum
(truncate)或
printf“%.0f”,sum
(舍入)

如果这不能解决您的问题,我希望看到您的输入使用
hd file.txt进行十六进制转储

尝试:

grep WILSON file_in.txt | sed 's/.*\x09//;s/\r//' | awk '{s+=$0}END{print s}'
  • s/*\x09/-删除所有小于或等于
    \x09
    字符的内容
  • s/\r/
    -删除文件末尾的dos行
在awk中过滤会更快:

sed 's/.*\x09//;s/\r//' file_in.txt | awk '/WILSON/{s+=$0}END{print s}'
尝试:

  • s/*\x09/-删除所有小于或等于
    \x09
    字符的内容
  • s/\r/
    -删除文件末尾的dos行
在awk中过滤会更快:

sed 's/.*\x09//;s/\r//' file_in.txt | awk '/WILSON/{s+=$0}END{print s}'

temp.dat
文件中,您可以尝试:

awk '{s+=$1} END {print s}' temp.dat

temp.dat
文件中,您可以尝试:

awk '{s+=$1} END {print s}' temp.dat

您的基本问题是,您的文件有Windows行结尾(CR-LF),CR(aka
\r
aka control-M)看起来像是bash使用的普通字符。你可以得到r