在bash中添加类似的行

时间:2018-09-26 17:10:21

标签: bash shell awk

我有一个包含以下记录的文件:

$ cat sample.txt
ABC,100
XYZ,50
ABC,150
QWE,100
ABC,50
XYZ,100

期望输出为:

$ cat output.txt
ABC,300
XYZ,150
QWE,100

我尝试了以下脚本:

PREVVAL1=0
SUM1=0
cat sam.txt | sort >  /tmp/Pos.part
while read line
do
VAL1=$(echo $line | awk -F, '{print $1}')
VAL2=$(echo $line | awk -F, '{print $2}')
if [ $VAL1 == $PREVVAL1 ]
then
SUM1=` expr $SUM + $VAL2`
PREVVAL1=$VAL1
echo $VAL1 $SUM1
else
SUM1=$VAL2
PREVVAL1=$VAL1
fi
done < /tmp/Pos.part

我想要一个衬板命令来获取所需的输出。想要避免while循环概念。我只想在第一列相同的地方添加数字,并在一行中显示。

3 个答案:

答案 0 :(得分:2)

awk -F, '{a[$1]+=$2} END{for (i in a) print i FS a[i]}' sample.txt

输出

QWE,100
XYZ,150
ABC,300

对每一行执行第一部分,并创建一个关联数组。 END部分将打印此数组。

答案 1 :(得分:1)

这是awk单线:

awk -F, -v OFS=, '{sum[$1]+=$2} END {for (key in sum) print key, sum[key]}' sample.txt > output.txt

sum[$1] += $2创建一个关联数组,其键是第一个字段,值是对应的总和。

答案 2 :(得分:1)

在本机bash中也可以轻松完成此操作。以下代码不使用任何外部工具,没有子shell,也没有管道,因此比您的原始代码 far 更快(我将钱花在典型/合理系统上的吞吐量的100倍上)

declare -A sums=( )
while IFS=, read -r name val; do
  sums[$name]=$(( ${sums[$name]:-0} + val ))
done

for key in "${!sums[@]}"; do
  printf '%s,%s\n' "$key" "${sums[$key]}"
done

如果愿意,可以将其设置为单线:

declare -A sums=( ); while IFS=, read -r name val; do sums[$name]=$(( ${sums[$name]:-0} + val )); done; for key in "${!sums[@]}"; do printf '%s,%s\n' "$key" "${sums[$key]}"; done