计算一行中出现的第一个字母,并使用grep在shell/linux中显示摘要

计算一行中出现的第一个字母,并使用grep在shell/linux中显示摘要,shell,grep,Shell,Grep,我有一个像这样的日志 I:5000:GAME I:5000:GAME I-:5000:GAME I-:5000:GAME E:5000:GAME E:5000:GAME E:5000:GAME E:5000:GAME E:5000:GAME J:5000:GAME J:5000:GAME J:5000:GAME L:5000:GAME M:5000:GAME K:5000:GAME 我想做的是计算以字母E,I-,J开头的行,然后按降序排序 样本输出 5 E 3 J 2 I- 这就是我想

我有一个像这样的日志

I:5000:GAME
I:5000:GAME
I-:5000:GAME
I-:5000:GAME
E:5000:GAME
E:5000:GAME
E:5000:GAME
E:5000:GAME
E:5000:GAME
J:5000:GAME
J:5000:GAME
J:5000:GAME
L:5000:GAME
M:5000:GAME
K:5000:GAME
我想做的是计算以字母E,I-,J开头的行,然后按降序排序

样本输出

5  E
3  J
2  I-
这就是我想输入的内容

sort /home/prod-dev/progex_logs.txt | egrep '^E|^I|^J' | cut -f1 -d: | uniq -c

我的文件是progex|u logs.txt,但它没有显示我想要的答案

这将使用给定的模式执行扩展grep。结果将传递给wc命令,以计算从egrep生成的行数。

尝试以下操作:

sort data | cut -f1 -d: | uniq -c
这将按词汇对输入数据进行排序,只提取第一列,然后将结果传递到
uniq-c
,这将折叠重复的行并计算折叠的行数。给定示例输入,这将生成:

  5 E
  2 I-
  2 I
  3 J
  1 K
  1 L
  1 M
如果只需要E、I和J,可以使用user2254435发布的
egrep
命令过滤掉它们,如下所示:

sort data | egrep '^I-|^E|^J'  | cut -f1 -d: | uniq -c
这会让你:

  5 E
  2 I-
  3 J
那么这有什么用呢? 第一个命令:

sort data
生成按词汇排序的数据版本。根据你的样品 输入,我们得到:

E:5000:GAME
E:5000:GAME
E:5000:GAME
E:5000:GAME
E:5000:GAME
I-:5000:GAME
I-:5000:GAME
I:5000:GAME
I:5000:GAME
J:5000:GAME
J:5000:GAME
J:5000:GAME
K:5000:GAME
L:5000:GAME
M:5000:GAME
然后,我们使用
|
操作符,它允许我们从一个命令向另一个命令发送stdout 另一个命令的stdin。此命令作为输入读取输出 从
sort
命令中,提取第一个(
-f1
) 冒号分隔的字段(
-d:
)。这给了我们:

E
E
E
E
E
I-
I-
I
I
J
J
J
K
L
M
5 E
然后,我们通过管道将输出传输到
uniq-c
,这将折叠重复的行 并生成折叠了多少行的计数。因此,考虑到 输入如下:

E
E
E
E
E
运行
uniq-c
可以为我们提供:

E
E
E
E
E
I-
I-
I
I
J
J
J
K
L
M
5 E
有关所有这些的更多信息,请参阅的手册页,
,和。

您可以使用awk执行此操作

cat ip.txt | awk 'BEGIN{IC=0;JC=0;EC=0}{if(index($0,"I-")>0)IC++;else if(index($0,"E:")>0)EC++;else if(index($0,"J:")>0)JC++;}END{printf("I- %d\n",IC);printf("E: %d\n",EC);printf("J: %d\n",JC);}'

这是使用
awk

awk -F: '/^(E|I-|J)/ {a[$1]++} END {for (i in a) print i,a[i]}' file
I- 2
E 5
J 3

要对其进行排序,您可以执行以下操作:

awk -F: '/^(E|I-|J)/ {a[$1]++} END {for (i in a) print i,a[i]}' file | sort -rk2
E 5
J 3
I- 2

工作原理

awk -F: '                   # setting field separator to :
/^(E|I-|J)/ {               # run this section only if starting with E, I- or J
    a[$1]++}                # add field #1 to array a
END {                       # end section
    for (i in a)            # looping through all element in array
    print i,a[i]}           # print element name and the number of elements
    ' file | sort -rk2      # sort output by column #2 in reverse order

我不认为这会给他提供他想要的示例输出,这是具有相同初始字段的行数的汇总。你是对的。我应该更仔细地阅读这个问题。拉尔克斯爵士,这个代码做什么“| cut-f1-d:|”?如果你能解释一下,既然是初学者。谢谢我用一些解释性的注释更新了我的答案。这是我输入的,但它没有运行sort/home/prod dev/progex|u logs.txt | egrep'^E | ^I | ^J'| cut-f1-d:| uniq-cComments对这类事情并没有真正的好处。使用您运行的命令更新您的问题,以及(a)它产生了什么错误或(b)输出是什么样子的。如果输出中只需要
I-
而不需要
I
,则需要修改
egrep
命令:
sort/home/prod dev/progex_logs.txt | egrep'^E | I-^J'| cut-f1-d:| uniq-c
如果确实需要反转字段,请将
uniq-c
的输出管道连接到
awk'{print$2,$1}。另外,请看我对Raghuram的回答的评论,其中显示了如何使用
awk
完成整个过程。这是一个极其复杂的
awk
命令。考虑<代码> AWK-F:'$ 1 ~/E.jj i/{ToTales [$ 1 ] ++}结束{ for(i in toTales)打印i,toTals[i] } 代码不复杂。逻辑是我有3个变量用于3个模式(每个模式一个)。根据图案增加计数器,并进行打印。你的想法也很好。就像你读了我对拉古拉姆答案的评论,然后把它变成了你自己的一样。@larsks我没有使用你的任何解决方案,我自己写了,所以给一个负号并不可怕。这只是使用
awk
的一种正常方式,我现在先看看你的评论。