每分钟在名为“data_logs”的目录中生成一个日志文件
日志文件名:
abc.log.2019041607
abc.log.2019041608..
日志文件的内容如下
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:0
R_MT|D:1234|ID:413|S:0
R_MT|D:1234|ID:413|S:0
R_MT|D:1234|ID:413|S:0
R_MT|D:1234|ID:413|S:0
k_MT|D:1234|ID:414|S:1
k_MT|D:1234|ID:414|S:1
k_MT|D:1235|ID:413|S:1
k_MT|D:1235|ID:413|S:1
我正在编写一个shell脚本,执行时它会查找最近5分钟创建的文件(最后5个文件,每分钟创建1个文件),逐个打开每个文件并进行处理,即创建一个输出。 txt 文件,其中包含,
R_MT|D:1234|ID:413
对于此组合,'s' 为 0 的总计数存储在“已提交”列中,'s'=1 存储在未提交列中
我的output.txt 需要如下所示:
Type, Number,ID,submitted,notsubmitted
R_MT,D:1234,ID:413,5,10
R_MT,D:1234,ID:414,0,2
R_MT,D:1235,ID:413,0,2
我用它来获取已提交和未提交的值:
zcat abc.log.2019041607.gz |grep "R_MT"|awk -F"|" '{print $2","$3","$4}'|sort|uniq -c
5 D:1234,ID:413,S:0
10 D:1234,ID:413,S:1
2 D:1234,ID:414,S:1
2 D:1235,ID:413,S:1
通过上面的命令,我得到了计数,但我不知道如何将其分配给变量,以便我可以写入输出文件中的“已提交”和“未提交”字段,并且我不知道如何获取最后 5 分钟的文件?
请帮助我,非常感谢!
答案1
当 input.log 作为你的输入时,我有这个可以与 gawk 一起使用,但仍在努力用 awk 找出答案:
cat input.log |
gawk -F"|" \
#print the header
'BEGIN{print"Type, Number,ID,submitted,notsubmitted"}
#only work on non empty lines
NF>0{
#create an ID from the first three fields
n=$1","$2","$3;
#everytime the ID pops up, increment subindex 1 or 2 depending on the value of field 4
if($4=="S:1"){
array[n][2]++}
else{
array[n][1]++}
}
#print the final array
END{for(i in array){
#if the value has never been seen declare it to be zero
if(array[i][1]){
m=array[i][1]}
else {
m=0}
if(array[i][2]){
n=array[i][2]}
else {
n=0}
print i","m","n}
}'
答案2
要查找最近 5 分钟内修改的日志文件,您可以使用find
.例如
find data_logs/ -type f -name 'abc.log.*' -mmin -6
这会找到修改少于的日志文件6几分钟前,这对于大多数用途来说应该足够了。如果您需要精确的文件修改时间,请使用:
find data_logs/ -type f -name 'abc.log.*' \( -mmin -5 -o -mmin 5 \)
它将查找不到 5 分钟前或正好 5 分钟前修改的文件。
从man find
:
-mmin n File's data was last modified n minutes ago.
和:
数字参数可以指定为
+n for greater than n, -n for less than n, n for exactly n.
答案3
交叉发布的问题https://stackoverflow.com/q/57377173/3220113已被搁置。我将在这里复制已接受的答案,其他问题可以删除。
对于一个文件: 首先使流易于使用 awk 进行处理(可以全部在 awk 中完成,以获得稍微更好的性能):
sed -nr 's/\|/,/g;s/(^R_MT,.*),S:([^ ]) *$/\1 \2/p' <(zcat abc.log.2019041607.gz)
结果(添加额外测试线后)
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 0
R_MT,D:1234,ID:413 0
R_MT,D:1234,ID:413 0
R_MT,D:1234,ID:413 0
R_MT,D:1234,ID:413 0
R_MT,D:1234,ID:414 1
R_MT,D:1234,ID:414 1
R_MT,D:1235,ID:413 1
R_MT,D:1235,ID:413 1
现在在 awk 中对它们进行计数,使用数组 a 作为字段名。
sed -nr 's/\|/,/g;s/(^R_MT,.*),S:([^ ]) *$/\1 \2/p' <(zcat abc.log.2019041607.gz) |
awk '{a[$1]; if ($2>0) notsub[$1]++; else submit[$1]++;}
END {for (i in a) print i "," submit[i]+0 "," notsub[i]+0;}
'
对于 5 个文件,首先确定您想要的结果。每个文件都有不同的输出文件:使用类似的循环
while IFS= read -r filename; do
... <( zcat "${filename}") ...
done < <(find datalogs -type f -name "abc*" -mmin -5)
5 个文件的结果相加为一个总和
... <( find datalogs -type f -name "abc*" -mmin -5 -exec zcat {} \;) ...
答案4
根据您喜欢的时间查找文件很容易。但是要获得结果,您可以awk
像这样使用:
awk -F\| '!/^\s*$/{if($4=="S:0"){Arr0[$1","$2","$3]+=1} else {Arr1[$1","$2","$3]+=1}}END{for(i in Arr1){print i,",",Arr0[i],",",Arr1[i]}}'
解释:
-F\|:定义
|
为字段分隔符!/^\s*$/: 跳过空行
if(Clause){Statement}else{statement}
: 清除END{...}
:当运算符丰富到 EOF 时执行此块