我输入文件如下
100A 2000
100B 150
100C 800
100A 1000
100B 100
100C 300
我想在第1列中为第1列中的每个uniq值减去值 因此输出应该看起来像
100A 1000
100B 50
100C 500
我试过了
awk '{if(!a[$1])a[$1]=$2; else a[$1]=$2-a[$1]}END{ for(i in a)print i" " a[i]}' file
但输出的是:
100A 0
100B 0
100C 0
请告知
答案 0 :(得分:2)
同一主题有很多(轻微)变化。
awk '
!($1 in a) {a[$1]=$2; next}
{a[$1]-=$2}
END {for (i in a) printf "%s %d\n",i,a[i]}
' input.txt
如果你愿意,可以将它叠加成一行。
请记住,awk结构由多个condition { statement }
对组成,因此您有时可以比使用if..else
更优雅地表达您的要求。 (并不是说这就是这种情况 - 这是一个简单的awk脚本,它可能无关紧要,除非你是一个纯粹主义者。:])
另外,请注意在问题中if
的条件下按照您的方式测试值。请注意a[$1]
两者测试该数组索引处的值是否为非和导致索引以空值存在(如果之前不存在)存在。如果要检查索引是否存在,请使用$1 in a
。
根据您对问题的评论进行更新...
如果你想从第一个条目中减去 last ,忽略其间的那些,那么你需要记录你的第一次和你的持续时间。这样的事情就足够了。
awk '
!($1 in a){a[$1]=$2;next}
{b[$1]=$2}
END {for(i in b)if(i in a)print i,a[i]-b[i]}
' input.txt
请注意,如Ed所述,这会以随机顺序生成输出。如果您希望输出有序,则需要一个额外的数组来跟踪订单。例如,这将使用首次看到项目的顺序:
awk '
!($1 in a) {
a[$1]=$2;
o[++n]=$1;
next
}
{
b[$1]=$2
}
END {
for (n=1;n<=length(o);n++)
print o[n],a[o[n]]-b[o[n]]
}
' i
请注意,用于确定数组中元素数量的length()
函数在awk的方言中并不普遍,但它在gawk和one-true-awk中都有效(在FreeBSD和其他方面使用) )。
答案 1 :(得分:1)
这个awk one-liner完成了这项工作:
awk '{if($1 in a)a[$1]=a[$1]-$2;else a[$1]=$2}
END{for(x in a) print x, a[x]}' file
答案 2 :(得分:1)
在awk中。使用条件运算符进行值放置/减法以保持紧密:
$ awk '{ a[$1]+=($1 in a?-$2:$2) } END{ for(i in a)print i, a[i] }' file
100A 1000
100B 50
100C 500
说明:
{
a[$1]+=($1 in a?-$2:$2) # if $1 in a already, subtract from it
# otherwise add value to it
}
END {
for(i in a) # go thru all a
print i, a[i] # and print keys and values
}
答案 3 :(得分:1)
根据您提供的样本输入,您只需要:
$ awk '$1 in a{print $1, a[$1]-$2} {a[$1]=$2}' file
100A 1000
100B 50
100C 500
如果这不是您所需要的,那么提供更具真实代表性的样本输入/输出,其中包括那些不够好的情况。
答案 4 :(得分:0)
您可以使用此awk
:
awk 'a[$1]{a[$1]=a[$1]-$2; next} {a[$1]=$2} END{for(v in a){print v, a[v]}}' file