要求:假如现在有个文本foo-t1.txt,格式如下:
a 1
b 2
c 3
b 4
a 5
d 6
f 7
g 8
c 9
d 10
左边一列是随机的字母,右边一列是随机的数字,然后要求写个脚本输出格式为:
a 6
b 6
c 12
d 16
f 7
g 8
脚本如下:
root@ubuntu:~/test# awk '{arr[$1] = arr[$1] + $2};END {for (item in arr) print item,arr[item]}' sum-t6.txt
a 6
b 6
c 12
d 16
f 7
g 8
拆开如下:
#!/bin/bash
declare -A arr
file=$1
awk '
{
arr[$1]=arr[$1]+$2
}
END{
for(n in arr){
print n,arr[n]
}
}' $file
root@ubuntu:~/test# ./t6-3.sh sum-t6.txt
a 6
b 6
c 12
d 16
f 7
g 8
或者
#!/bin/bash
for fir in {a..z} {A..Z}
do
grep $fir /root/test/sum-t6.txt > /dev/null
if [ "$?" -eq "0" ];then
grep "$fir" /root/test/sum-t6.txt|awk '{sum+=$2}END{print $1," ",sum}'
fi
done
注意sum+=$2,是先加后赋值,之前手误写成=+,会少加第一次的数值,计算结果不对。
或者:
#!/bin/bash
declare -A HW
declare -A line
File=$1
while read line
do
cols=($line)
HW[${cols[0]}]+=${cols[1]}
done < $File
for key in ${!HW[*]}
do
echo "$key ${HW[$key]}"
done
延伸题:[linux@test /tmp]$ cat test
aaa 123.52
bbb 125.54
aaa 123.52
aaa 123.52
ccc 126.36
对文件test中 第一列为aaa的行求和
[linux@test /tmp]$ awk '/aaa/ {sum += $2};END {print sum}' test
370.56
或者后来两个脚本,其中可以看到print 和printf函数的区别,一个可以直接打印格式,一个可以用符号来打印格式:
#!/bin/bash
for fir in {a..z}
do
grep $fir /root/test/sum-t6.txt > /dev/null
# [ "$?" -eq "0" ] && grep "$fir" /root/test/sum-t6.txt|awk '{sum+=$2}END{print $1," ",sum}'
done
和下面的是等价的:
#!/bin/bash
for fir in {a..z}
do
grep $fir /root/test/sum-t6.txt > /dev/null
[ "$?" -eq "0" ] && grep "$fir" /root/test/sum-t6.txt|awk '{sum+=$2}END{printf ("%-3s %-5s\n",$1,sum)}'
done
所有的输出为:
root@ubuntu:~/test# ./t6.sh
a 6
b 6
c 12
d 16
f 7
g 8
注意字符集是这样的{a..z}{0..9},for alph in [a-z]这个表达不对。需要改为 for alph in {a..z}。
但是一个问题是,比如要匹配大小写字母:
for alph in {a..z} 可以匹配alph在小写字母里面,我也知道 for alph in {A..Z}可以匹配alph在大写字母里面。但是怎么表达这个要匹配的在大小写字母里面?
答:
for alph in {a..z} {A..Z}