![在 bash 脚本中提取、剪切、处理字符串](https://linux22.com/image/140764/%E5%9C%A8%20bash%20%E8%84%9A%E6%9C%AC%E4%B8%AD%E6%8F%90%E5%8F%96%E3%80%81%E5%89%AA%E5%88%87%E3%80%81%E5%A4%84%E7%90%86%E5%AD%97%E7%AC%A6%E4%B8%B2.png)
我基本上有 4 个 txt 文件,其中包含诸如
FILE 1
localhost_access_2018-07-19.tar.gz:13
localhost_access_2018-07-20.tar.gz:17
localhost_access_2018-07-21.tar.gz:12
localhost_access_2018-07-22.tar.gz:4
localhost_access_2018-07-23.tar.gz:2
localhost_access_2018-07-24.tar.gz:2905
localhost_access_2018-07-25.tar.gz:10440
localhost_access_2018-07-26.tar.gz:2644
localhost_access_2018-07-27.tar.gz:1896
localhost_access_2018-07-28.tar.gz:1238
localhost_access_2018-07-29.tar.gz:932
FILE 2
localhost_access_2018-06-19.tar.gz:0
localhost_access_2018-06-20.tar.gz:0
localhost_access_2018-06-21.tar.gz:1
localhost_access_2018-06-22.tar.gz:0
localhost_access_2018-06-23.tar.gz:0
localhost_access_2018-06-24.tar.gz:0
localhost_access_2018-06-25.tar.gz:0
localhost_access_2018-06-26.tar.gz:1
localhost_access_2018-06-27.tar.gz:0
localhost_access_2018-07-04.tar.gz:2
localhost_access_2018-07-05.tar.gz:3
localhost_access_2018-07-06.tar.gz:6
localhost_access_2018-07-07.tar.gz:0
localhost_access_2018-07-19.tar.gz:15
ETC。
4 个文件中的每一个都有冗余的日期,例如在本例中,localhost_access_2018-07-19.tar.gz:15
但最终数字不同(在:之后)。
对于相同的日期,我必须:剪切“ local_host_access_
”,仅将日期保留在一个新的 txt 文件中(不更改其值和格式),并且我必须剪切 .tar.gz。
此外,我必须对相同日期的每个值求和:
因此,如果 4 个不同文件中有 4 个“localhost_access_2018-07-19”日期,我必须对值 .gz:“XYZ”后的每个数字 XYZ 求和。
例子:
localhost_access_2018-07-19.tar.gz:1
localhost_access_2018-07-19.tar.gz:2
localhost_access_2018-07-19.tar.gz:3
localhost_access_2018-07-19.tar.gz:4
应该在新文件中以文本的单个输出返回
2018-07-19:10
我已经把我尝试作为答案,但我希望有更好的解决方案(和解释)。谢谢。
答案1
也尝试一下这个简单的awk
方法:
awk -F"[_.:]" ' # set field separator to "_", ".", or ":"
{SUM[$3] += $NF # sum all trailing fields in array indexed by the date
}
END {for (s in SUM) print s, SUM[s] # print the date and the respective sum
}
' OFS=":" file[123] # set output field separator; have shell expand file names 1 - 3
答案2
awk -F 'localhost_access_' '
{
n=substr($2,1+index($2,":"));
gsub(".tar.gz.*","",$2);
str[$2]+=n
}
END{
for (i in str){
print i":"str[i]
}
}' node1.txt node2.txt node3.txt node4.txt | sort -to > output.txt
output_not_sorted=$(cat output.txt);
# sort output by date
exit
让我知道这是否可以改进。
答案3
考虑到您在问题开始时显示的两个文件,并假设它们实际上不包含空行:
$ awk -F ':' -v OFS=':' '
{ sum[$1]+=$2 }
END { for (key in sum) {
split(key,f,"[_.]")
print f[3],sum[key] } }' file* | sort
2018-06-19:0
2018-06-20:0
2018-06-21:1
2018-06-22:0
2018-06-23:0
2018-06-24:0
2018-06-25:0
2018-06-26:1
2018-06-27:0
2018-07-04:2
2018-07-05:3
2018-07-06:6
2018-07-07:0
2018-07-19:28
2018-07-20:17
2018-07-21:12
2018-07-22:4
2018-07-23:2
2018-07-24:2905
2018-07-25:10440
2018-07-26:2644
2018-07-27:1896
2018-07-28:1238
2018-07-29:932
使用文件名作为关联数组中的键sum
,并收集其中每个文件名的总和。最后,迭代 的键sum
并打印出每个键的日期部分以及总和。键的日期部分是按点和下划线分割后的第三个字段。
结果是管道虽然sort
。
更短,但本质上与上面相同(但仅使用日期作为数组中的键sum
):
awk -F '[_.:]' -v OFS=':' '
{ sum[$3]+=$6 }
END { for (d in sum) print d, sum[d] }' file*
答案4
#!/bin/bash
# Sum duplicate row values with awk ; Columns 3 and 6
awk -F '[_.:]' '{seen[$3]+=$6}END{for (i in seen) print i, seen[i]}' OFS=":" node[1-4].txt |
sort > log.txt
“# 使用 awk 求和重复行值”的来源 https://stackoverflow.com/questions/42024296/sum-duplicate-row-values-with-awk