猫管道awk操作与文件上的awk命令的比较



在尝试优化一些与服务器相关的数据时,我和我的团队就linux命令的使用进行了讨论。请各位成员帮助我们更准确地理解这个概念。

在服务器上,我们有每分钟创建一次的日志文件,我们需要搜索带有特定标签的日志,例如:错误日志、超时日志、请求失败日志。在许多要求中,一个要求是提供有关这些标签计数的信息

简单的逻辑是awk特定字段(带分隔符)进行排序,并使用uniq-c命令计算此类实例的数量。

我可以看到两种执行方式:

cat fname | awk -F":" {'print $1'} | sort | uniq -c

awk -F":" {'print $1'} fname | sort | uniq -c

文件大小可以以GB为单位,因此哪个命令可能更有效。

有三种方法可以打开文件并让awk对其内容进行操作:

  1. cat打开文件:

    cat file | awk '...'
    
  2. shell重定向打开文件:

    awk '...' < file
    
  3. awk打开文件

    awk '...' file
    

这些选择中:

  1. 总是要避免,因为cat和管道正在使用资源,并且没有提供任何值,请谷歌UUOC(Useless UseOf Cat)了解详细信息

使用其他2种中的哪一种是有争议的:

  1. 优点是shell打开的是文件而不是工具,因此如果对所有工具都这样做,则可以依赖一致的错误处理
  2. 优点是该工具知道它正在操作的文件的名称(例如awk中的FILENAME),因此您可以在内部使用它

要查看差异,请考虑以下两个文件:

$ ls -l file1 file2
-rw-r--r-- 1 Ed None 4 Mar 30 09:55 file1
--w------- 1 Ed None 0 Mar 30 09:55 file2
$ cat file1
a
b
$ cat file2
cat: file2: Permission denied

看看当你试图使用两种打开它们的方法在两者的内容上运行awk时会发生什么:

$ awk '{print FILENAME, $0}' < file1
- a
- b
$ awk '{print FILENAME, $0}' file1
file1 a
file1 b
$ awk '{print FILENAME, $0}' < file2
-bash: file2: Permission denied
$ awk '{print FILENAME, $0}' file2
awk: fatal: cannot open file `file2' for reading (Permission denied)

请注意,当您使用重定向时,打开不可读文件file2的错误消息来自shell,因此看起来与我第一次尝试cat时的错误消息完全相同,而让awk打开它时的错误信息来自awk,与shell消息不同,在不同的awk中也会有所不同。

请注意,当使用awk打开文件时,FILENAME填充有正在操作的文件的名称,但当使用重定向打开文件时则设置为-

我个人认为"3"(填充的FILENAME)的好处远远超过了"2"(文件打开错误的一致错误处理)的好处,所以我总是使用:

awk '...' file

对于你的特定问题,你会使用:

awk -F':' '{cnt[$1]++} END{for (i in cnt) print cnt[i], i}' fname

应该使用来避免毫无用处的cat

awk -F":" '{print $1}' fname | sort | uniq -c

但我的建议是,通过使用在awk中查找唯一项目,甚至可以避免昂贵的sortuniq命令

awk -F":" '!seen[$1]++' fname

这将打印独特的线条。

获取唯一计数:

awk -F":" '!count[$1]++{c++} END{print c}' fname

cat fname |的速度稍微慢了一点,因为它必须将文件从磁盘复制到内核,然后复制到cat的缓冲区,然后再复制到一个管道,该管道再次到达内核,然后再到另一个进程。这不是很多,因为它应该只是一个线性的慢下来,内存中的复制也很快,但你可以总是(=不依赖于some_command接受文件参数)通过替换来加快速度

cat one_file_name | some_command 

带有

<one_file_name some_command

这将更快,因为它将直接将one_file_name设置为some_commandstdin

<one_file_name可以并且经常被放置在some_command之后和下一个管道符号之前。我个人经常喜欢从它开始,因为它反映了cat(cat one_file_name)从左到右的无用但有点常见的用法。

最新更新