首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Bash:将数字与相应的名称相加

Bash:将数字与相应的名称相加
EN

Stack Overflow用户
提问于 2013-02-16 07:02:12
回答 3查看 159关注 0票数 0

我有一个文件(已排序),如下所示:

代码语言:javascript
运行
复制
alma-court, 1, 0, 8
alma-court, 4, 2, 24
atlantic-house, 99, 1, 340
diamond, 2, 2, 16
iminds-zuiderpoort, 0, 1, 0
north-plaza, 18, 3, 718
north-plaza, 90, 2, 19

我想为每个相同的第一列计算一个垂直合计。

所以对于alma-court,我想得到1+4,0+2和8+24的总和。大西洋之家已经很好了,因为这是唯一的情况。北广场应该是18+90,3+2和718+19。

并像这样打印所有内容:

代码语言:javascript
运行
复制
alma-court, 5, 2, 32
atlantic-house, 99, 1, 340
...

有人能用Bash给我解决方案吗?

谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-02-16 09:08:53

代码语言:javascript
运行
复制
groups=( $( cut -d ',' -f 1 count.txt | sort -u ) )

for group in "${groups[@]}"
do
  grep $group count.txt | awk '{ sum1+=$2; sum2+=$3; sum3+=$4;} END {print $1 " " sum1 ", " sum2 ", " sum3}'
done

anew@buddha:~/dev/so$ bash so.sh 
alma-court, 5, 2, 32
atlantic-house, 99, 1, 340
diamond, 2, 2, 16
iminds-zuiderpoort, 0, 1, 0
north-plaza, 108, 5, 737
票数 0
EN

Stack Overflow用户

发布于 2013-02-16 07:55:37

您可以将其用作bash script的基础

代码语言:javascript
运行
复制
set -u
tr -d "," < data2 | while read name col1 col2 col3 ; do
    echo name=$name col1=$col1 col2=$col2 col3=$col3
done

其中data2是已排序的文件。

它给出了以下内容,从那里你应该能够检测到'name‘的变化,并进行计算。

代码语言:javascript
运行
复制
name=alma-court col1=1 col2=0 col3=8
name=alma-court col1=4 col2=2 col3=24
name=atlantic-house col1=99 col2=1 col3=340
name=diamond col1=2 col2=2 col3=16
name=iminds-zuiderpoort col1=0 col2=1 col3=0
name=north-plaza col1=18 col2=3 col3=718
name=north-plaza col1=90 col2=2 col3=19

编辑添加的Perl版本以确保完整性。

代码语言:javascript
运行
复制
use strict;
my %names;
while(<>) {
    my @F = split(',');
    my $name = shift @F;
    foreach my $x (0..$#F) {
        $names{$name}[$x] += $F[$x];
    }
}
foreach my $key ( sort keys %names ){
    print $key, " ", join(" ", @{$names{$key}}), "\n";
}

使用as perl myperl.pl < yourdata给出

代码语言:javascript
运行
复制
alma-court 5 2 32
atlantic-house 99 1 340
diamond 2 2 16
iminds-zuiderpoort 0 1 0
north-plaza 108 5 737
票数 2
EN

Stack Overflow用户

发布于 2013-02-16 08:48:17

使用awk (除非您知道或想要学习Perl或Python):

代码语言:javascript
运行
复制
awk '{ sum[$1,0] += $2; sum[$1,1] += $3; sum[$1,2] += $4; names[$1] = 1; }
     END { for (name in names)
               printf "%s %d, %d, %d\n", name, sum[name,0], sum[name,1], sum[name,2];
         }' <<EOF
alma-court, 1, 0, 8
alma-court, 4, 2, 24
atlantic-house, 99, 1, 340
diamond, 2, 2, 16
iminds-zuiderpoort, 0, 1, 0
north-plaza, 18, 3, 718
north-plaza, 90, 2, 19
EOF

输出:

代码语言:javascript
运行
复制
iminds-zuiderpoort, 0, 1, 0
alma-court, 5, 2, 32
north-plaza, 108, 5, 737
atlantic-house, 99, 1, 340
diamond, 2, 2, 16

如果希望名称按特定顺序排列,请对输出进行排序。请注意,名称包含尾随的逗号,因此打印格式不会在名称后添加逗号。

bash (4.x)实现

代码语言:javascript
运行
复制
{
declare -A sum
declare -A names

IFS=,
while read name v1 v2 v3
do
    names[$name]="$name"
    ((sum[${name}1] += $v1))
    ((sum[${name}2] += $v2))
    ((sum[${name}3] += $v3))
done 

for name in "${names[@]}"
do
    printf "%s, %d, %d, %d\n" $name ${sum[${name}1]} ${sum[${name}2]} ${sum[${name}3]}
done
} <<EOF
alma-court, 1, 0, 8
alma-court, 4, 2, 24
atlantic-house, 99, 1, 340
diamond, 2, 2, 16
iminds-zuiderpoort, 0, 1, 0
north-plaza, 18, 3, 718
north-plaza, 90, 2, 19
EOF

输出:

代码语言:javascript
运行
复制
diamond, 2, 2, 16
atlantic-house, 99, 1, 340
north-plaza, 108, 5, 737
alma-court, 5, 2, 32
iminds-zuiderpoort, 0, 1, 0

幸运的是,awkbash脚本的输出是相同的,给出或接受数据的排序顺序。

bash脚本使用了关联数组,这是bash 4.x的一个特性,而bash 3.x中没有这个特性。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14904825

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档