拆分字段,然后删除重复项

时间:2015-06-24 14:00:28

标签: awk

示例文件:

# cat test1 
-rw-r--r-- 1 root root   19460 Feb 10 03:56 catalina.2015-02-10.log
-rw-r--r-- 1 root root  206868 May  4 15:05 catalina.2015-05-04.log
-rw-r--r-- 1 root root  922121 Jun 24 09:26 catalina.out
-rw-r--r-- 1 root root       0 Feb 10 02:27 host-manager.2015-02-10.log
-rw-r--r-- 1 root root       0 May  4 04:17 host-manager.2015-05-04.log
-rw-r--r-- 1 root root    2025 Feb 10 03:56 localhost.2015-02-10.log
-rw-r--r-- 1 root root    8323 May  4 15:05 localhost.2015-05-04.log
-rw-r--r-- 1 root root     873 Feb 10 03:56 localhost_access_log.2015-02-10.txt
-rw-r--r-- 1 root root  458600 May  4 23:59 localhost_access_log.2015-05-04.txt
-rw-r--r-- 1 root root       0 Feb 10 02:27 manager.2015-02-10.log
-rw-r--r-- 1 root root       0 May  4 04:17 manager.2015-05-04.log

预期输出:

catalina
host-manager
localhost
localhost_access_log
manager

尝试1(有效):

# awk '{split($9,a,"."); print a[1]}' test1 | awk '!z[$i]++'
catalina
host-manager
localhost
localhost_access_log
manager

尝试2(工作):

# awk '{split($9,a,"."); print a[1]}' test1 | uniq
catalina
host-manager
localhost
localhost_access_log
manager

尝试3(失败):

# awk '{split($9,a,"."); a[1]++} {for (i in a){print a[i]}}' test1
1
2015-02-10
log
1
2015-05-04
log
1
out
.
.
.

问题:

我想拆分第9个字段,然后只显示uniq条目。但是,我想在一个awk单行中执行此操作。在第三次尝试时寻求帮助。

2 个答案:

答案 0 :(得分:5)

另一个更惯用的awk单行:

awk '!a[ $0 = substr($NF,1,index($NF,".")-1) ]++' file

或更明确地表达:

awk '{$0=substr($NF,1,index($NF,".")-1)} !a[$0]++' file
  • 我们使用well-known !a[$0]++重复数据删除技巧。
  • 但首先我们将$0更改为:substr($NF,1,index($NF,".")-1)
    • 整行成为最后一个字段$NF的子字符串,直到第一个点(.) - substr()index()的一些帮助

此解决方案的一个好处是您无需等到整个文件被解析。拆分字段是重复数据删除并即时打印。

答案 1 :(得分:2)

您必须使用END块来打印结果:

awk '{split($NF,a,"."); b[a[1]]} END{for (i in b){print i}}' file

注意:

  • 我正在使用$NF来抓住最后一个字段。这样,如果你碰巧有比9更多或更少的字段,它也会起作用(只要没有带空格的文件名,因为parsing ls is evil)。
  • 我们无法直接遍历a[]数组,因为它是包含分割数据的数组。为此,我们需要创建另一个数组,例如b[]。这就是我们说b[a[1]]的原因。单独,除非您想要跟踪任何项目出现的次数,否则无需b[a[1]]++
  • END块在处理完整个文件后执行。否则,您每个记录都会检查一次结果(即每行一次),然后出现重复项。