【问题标题】:Adding similar lines in bash [duplicate]在bash中添加类似的行[重复]
【发布时间】:2018-09-27 01:29:31
【问题描述】:

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

$ 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 循环的概念。我只想添加第一列相同的数字并将其显示在一行中。

【问题讨论】:

  • 使用awk会很容易,只需在关联数组中累加即可。
  • 您不需要使用awk 以逗号分隔行。使用while IFS=, read VAL1 VAL2
  • 我需要跳出 while 循环,只需要获得一些相同的线性命令。有可能吗?
  • 顺便说一句,考虑通过shellcheck.net 运行您的代码并修复它找到的内容。在现代代码中没有理由使用expr,并且为您处理的每一行运行一个新的awk 副本的管道非常效率低下。

标签: bash shell awk


【解决方案1】:
awk -F, '{a[$1]+=$2} END{for (i in a) print i FS a[i]}' sample.txt

输出

QWE,100
XYZ,150
ABC,300

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

【讨论】:

  • 我发现的一个问题是,如果值很大,则结果以指数格式出现,上面的命令@steffen
  • @Programmer 使用 gawk 而不是 awk。如果这还不够,并且您的整数非常大,请使用gawk -Mgawk --bignum
【解决方案2】:

这是一个awk 单线:

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

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

【讨论】:

  • 感谢您的宝贵时间..
【解决方案3】:

这也可以在本机 bash 中轻松完成。以下代码不使用外部工具、子shell 和管道,因此比您的原始代码快(我愿意将钱放在典型/合理系统上的吞吐量的 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 

【讨论】:

    猜你喜欢
    • 2019-05-03
    • 2015-04-09
    • 2016-10-19
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-26
    相关资源
    最近更新 更多