Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如何对多个文件中的多个单词引用进行grep,并将它们按行和列分组列出_Bash_Unix_Awk - Fatal编程技术网

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