Bash 如何对多个文件中的多个单词引用进行grep,并将它们按行和列分组列出
您好:需要您的帮助来计算多个文件中的单词出现次数,并将它们输出为行和列。我搜索了一个类似的参考网站,但无法找到,因此张贴在这里 设置: 我有以下两个文件Bash 如何对多个文件中的多个单词引用进行grep,并将它们按行和列分组列出,bash,unix,awk,Bash,Unix,Awk,您好:需要您的帮助来计算多个文件中的单词出现次数,并将它们输出为行和列。我搜索了一个类似的参考网站,但无法找到,因此张贴在这里 设置: 我有以下两个文件 [a.log] id,status 1,new 2,old 3,old 4,old 5,old [b.log] id,status 1,new 2,old 3,new 4,old 5,new 所需结果 仅使用命令行所需的结果最好是: file count(new) count(old) a.log 1
[a.log]
id,status
1,new
2,old
3,old
4,old
5,old
[b.log]
id,status
1,new
2,old
3,new
4,old
5,new
所需结果
仅使用命令行所需的结果最好是:
file count(new) count(old)
a.log 1 4
b.log 3 2
剧本
下面的脚本为我提供了一个单词跨多个单词的计数。
我一直在努力获取多个单词的结果。请帮忙
grep -cw "old" *.log
您可以使用gnu awk获得此输出,gnu awk接受要在命令行参数中搜索的逗号分隔单词:
awk -v OFS='\t' -F, -v wrds='new,old' 'BEGIN{n=split(wrds, a, /,/); for(i=1; i<=n; i++) b[a[i]]=a[i]} FNR==1{next} $2 in b{freq[FILENAME][$2]++} END{printf "%s", "file" OFS; for(i=1; i<=n; i++) printf "count(%s)%s", a[i], (i==n?ORS:OFS); for(f in freq) {printf "%s", f OFS; for(i=1; i<=n; i++) printf "%s%s", freq[f][a[i]], (i==n?ORS:OFS)}}' a.log b.log | column -t
PS:column-t仅用于以表格格式格式化输出
可读awk:
我认为你在寻找这样的东西,但如果你追求效率,你的目标是什么还不太清楚。例如,这不是太有效率
for file in *.log; do
echo -n "${file}\t"
for word in "new" "old"; do
grep -cw $word $file;
echo -n "\t";
done
echo;
done
为了可读性,我简化了第一行,但是如果文件名中有空格,这就不起作用了——正确的解决方案是将第一行改为read find-iname*.log-maxdepth=1 |读取文件时;执行Awk解决方案:
awk 'BEGIN{
FS=","; OFS="\t"; print "file","count(new)","count(old)";
f1=ARGV[1]; f2=ARGV[2] # get filenames
}
FNR==1{ next } # skip the 1st header line
NR==FNR{ c1[$2]++; next } # accumulate occurrences of the 2nd field in 1st file
{ c2[$2]++ } # accumulate occurrences of the 2nd field in 2nd file
END{
print f1, c1["new"], c1["old"];
print f2, c2["new"], c2["old"]
}' a.log b.log
输出:
file count(new) count(old)
a.log 1 4
b.log 3 2
用grep去掉标题,然后排序和计数
join -1 2 -2 2 a.luc b.luc
> new 1 3
> old 4 2
放置新标题是留给读者的练习。unix/linux/bash是否有翻转表的翻转命令,或者您怎么说
处理空单元格也是一项练习,但使用join也是可能的。如果没有真正的多维数组支持,这将计算字段2中的所有值,而不仅仅是新/旧值。标题和列数也随不同值的数量而动态变化
$ awk -F, 'NR==1 {fs["file"]}
FNR>1 {c[FILENAME,$2]++; fs[FILENAME]; ks[$2];
c["file",$2]="count("$2")"}
END {for(f in fs)
{printf "%s", f;
for(k in ks) printf "%s", OFS c[f,k];
printf "\n"}}' file{1,2} | column -t
file count(new) count(old)
file1 1 4
file2 3 2
那么,[a.log]与[b.log]是不同的文件吗?请注意,OP编写的目的是统计多个文件中的单词出现次数,这可能意味着超过2次files@anubhava,请注意,我有两个文件,其中+我已将结果显示为所需结果nr==1 | | FNR==1相当于FNR==1跳过一个表称为转置
for c in a b ; do egrep -o "new|old" $c.log | sort | uniq -c > $c.luc; done
join -1 2 -2 2 a.luc b.luc
> new 1 3
> old 4 2
$ awk -F, 'NR==1 {fs["file"]}
FNR>1 {c[FILENAME,$2]++; fs[FILENAME]; ks[$2];
c["file",$2]="count("$2")"}
END {for(f in fs)
{printf "%s", f;
for(k in ks) printf "%s", OFS c[f,k];
printf "\n"}}' file{1,2} | column -t
file count(new) count(old)
file1 1 4
file2 3 2