解决方案1

解决方案1

我有一个文件,其中包含许多行和 5 列的数字,如下所示:

1  2  3  4  5   
6  7  8  9  10   
11 12 13 14 15   
16 17 18 19 20   
21 22 23 24 25   
...

如果我想以这种方式获得第一行和第三行中的数字之和: 1+11, 2+12, 3+13, 4+14, 5+15 这意味着我最终想看到的是12 14 16 18 20 应该我愿意?

答案1

解决方案1

#!/bin/bash
{ read -ra line1; read _; read -ra line3; }
for i in "${!line1[@]}"; do
  result+=("$(( ${line1[i]} + ${line3[i]} ))")
done
printf %s\\n "${result[*]}"

例子:

$ bash script < yourfilename
12 14 16 18 20
$ 

脚本说明

{ read -ra line1; read _; read -ra line3; } 这部分读取文件的前三行,仅保留前两行。它还将它们分成数组 line1 和 line3。它假定来自标准输入的数据流。请参阅有关如何执行此操作的示例。

for i in "${!line1[@]}"; do result+=("$(( ${line1[i]} + ${line3[i]} ))"); done 此部分循环遍历两个数组之一的元素,并对 line1 和 line2 中的相同元素求和。结果被放入一个名为 result 的新数组中

printf %s\\n "${result[*]}" 以空格分隔打印计算出的数组元素。


解决方案2

另一种避免循环的解决方案,假设输入按要求有 5 列:

#!/bin/bash
{ read a b c d e; read _; read v w x y z; }
echo "$((a+v)) $((b+w)) $((c+x)) $((d+y)) $((e+z))"

例子:

$ cat yourfilename
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
...
$ bash script < yourfilename
12 14 16 18 20
$ 

脚本说明

{ read a b c d e; read _; read v w x y z; } 将第 1 行(或第 3 行)中的数字读入变量 a 至 e(或 v 至 z)

echo "$((a+v)) $((b+w)) $((c+x)) $((d+y)) $((e+z))" 根据要求打印以空格分隔的变量的总和

答案2

$ sed -n '1p;3p' file | datamash -W sum 1-5
12      14      16      18      20

首先sed仅用于输出第 1 行和第 3 行。然后将它们输入到 GNU 中datamash,GNU 被告知对第 1 列到第 5 列中的每个单独列求和。它-W指示datamash将任何连续的空格视为字段分隔符。

输出以制表符分隔。要获得空格分隔的输出,请使用--output-delimiter=' '以下选项datamash

$ sed -n '1p;3p' file | datamash -W --output-delimiter=' ' sum 1-5
12 14 16 18 20

答案3

awk 'NR==1 || NR==3 { for (i=1; i<=NF; i++) a[i]+=$(i)}END{for (i in a) printf "%s ", a[i]; print ""}'

例子:

$ awk 'NR==1 || NR==3 { for (i=1; i<=NF; i++) a[i]+=$(i)}END{for (i in a) printf "%s ", a[i]; print ""}'' yourfilename
12 14 16 18 20
$ 

编辑:要在第三个之后停止从文件中读取行,我们可以提前退出。不过,对于包含少于 10k 行的文件,您不会看到明显的差异。

awk 'NR==1 {split($0,a)} NR==3 {for (i in a) printf "%s ", a[i]+$i; print ""; exit}'

证明它适用于您的示例:

$ cat yourfilename
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
...
$ awk 'NR==1 {split($0,a)} NR==3 {for (i in a) printf "%s ", a[i]+$i; print ""; exit}' yourfilename
12 14 16 18 20
$ 

相关内容