在列和结果bash中计数

时间:2016-10-14 02:41:45

标签: bash shell

我有一个奇怪的项目

我有很长的档案。它的分隔列由' |'共有8个。 第8列。已列出浏览器(chrome,I.E,safari等)。 我需要按字母顺序打印它们,然后 每个用户打印它们。 例如:

Chrome 432
Safari 543
etc..

到目前为止我已经尝试了

grep -v "^#" < < file > | awk -F '|' '{ print $8 }' | sort | uniq -c

grep删除所有#条评论

awk获取第8列

然后sortuniq来打印&#39;结果

这就是我得到的:

2
2307 Internet Explorer
369 Safari
2785 Chrome
316 Opera
4182 Firefox

所以我首先需要摆脱那种无关紧要的&#39; 2&#39;在开始(我认为它必须是空白或其他)

脚本必须是&#34;通用&#34;所以我不能使用grep -c "Chrome"例如

如果我尝试在awk之后运行另一个uniq,结果会变得非常混乱

2 2785 4182x 2307net Explorer 316 369i

最后它似乎是第9列,因为&#34; Internet Explorer&#34;我怎样才能将它与第8列合并?

p.s我最大的问题是先获得名字,然后再获得麻烦

p.s 2我检查了这个帖子frequency count for file column in bash,我无法得到我想要的结果

我的文件的比例

#id|lastName|firstName|gender|birthday|creationDate|locationIP|browserUsed 1099511633435|Smith|Jack|male|1981-04-19|2010-05-26T03:45:11.772+0000|50.72.193.218|Internet Explorer 1099511635042|Kiss|Gyorgy|male|1984-09-14|2010-05-16T22:57:41.808+0000|91.137.244.86|Chrome 1099511635218|Law-Yone|Eric|male|1987-01-20|2010-05-26T20:10:22.515+0000|203.81.95.235|Chrome 1099511638444|Jasani|Chris|female|1981-05-22|2010-04-29T20:50:40.375+0000|196.223.11.62|Firefox 2199023256615|Arbelaez|Gustavo|male|1986-11-02|2010-07-17T18:53:47.633+0000|190.96.218.101|Chrome

2 个答案:

答案 0 :(得分:0)

尝试:

grep -v "^#" file | awk -F'|' '{print$8}' | sort | uniq -c | awk '{print$2,$3,$1}'

答案 1 :(得分:0)

你已经完成了这里的所有步骤,交换名称和数字的问题通常是另一个awk '{print$2,$3,$1}'管道的简单扩展(正如AFAbyss建议的那样,归功于他们!)或者通过sed -s "s/^\s\+\([0-9]\+\) \(.*\)$/\2 \1/"(其中说:找到一个数字序列后跟一个空格和一个任意字符串直到行尾,输出后者,一个空格和前者,并且具有不处理的轻微优势“Internet Explorer”作为两个字段,并且不期望没有浏览器名称最多只有两个字)。这应该工作,为什么不呢?令人不安的是,你的线条与预期的差别很大!

问题更严重

因此,输出被破坏的问题在其他地方,我几乎可以肯定它是行尾格式。请注意,在不同的系统中,行尾由不同的字符或字符组合标记:

LF (\n, \012) on Unices,
CR (\r, \015) on classic Macs,
CRLF (\r\n, \015\012) on Windows

heavily simplified)。如果您的文件是Microsoft Windows格式,Unix将读取\r作为该行的一部分!让我们看看典型行中会发生什么:

...|196.223.11.62|Firefox\r\n
                  =========
                  field 8

包含Firefox的所有行都会发生这种情况(因为它始终是最后一项,因此后面总是\r\n),因此sortuniq会这样做他们的工作很好,告诉你Firefox\r出现了4182次:

4182 Firefox\r\n
==== =========**
cnt  output   EOL

这是一个不可见的问题。 \r做的是回车,它会将光标返回到行的开头。以下\n前进到下一行。想打字机:一直向右推,然后拉动手柄。在电子打字机中,它只是一个NL键按下,这就是为什么Unix会记录它的原因,\r现在是多余的,但如果它刚好在\n之前就不会破坏输出。

但是现在当你尝试交换线路的两个部分时:

Firefox\r 4182\n
========= ====**
output    cnt EOL

这是一场灾难。打印Firefox,然后马车返回最左侧的列,然后打印4182 重写之前键入的内容。数字之前实际上有两个空格,因为您指示awk打印$2,然后$3(空),然后$1awk插入空格两者之间。你会得到

Firefox\r   (field $2 is printed, resulting in the carriage returned to left)
↑
␣irefox\r   (space between $2 and $3)
 ↑
␣irefox\r   (field $3 is printed)
 ↑
␣␣refox\r   (space between $3 and $1)
  ↑
␣␣4812x\r   (field $1 is printed)
      ↑

然后换行。这不是一个错误,它是一个常用于程序的功能,它有兴趣重写最后一行,而不必每次都输出一个新行(mplayerwget,...)。错误是在输入行的末尾有一个额外的\r

如何解决?

一种方法是通过dos2unix运行您的整个输入,将\r\n的任何出现转换为\n。但这不是必要的。如果您使用我的sed替代方案,只需告诉它在正则表达式中\r而不是\n$)之前停止:

grep -v \# file \
  | cut -d \| -f 8 \
  | sort \
  | uniq -c \
  | sed -s "s/^\s\+\([0-9]\+\) \(.*\)\r/\2 \1/"
                                     ↑↑