cat管awk操作与awk命令在文件上的比较

时间:2015-03-30 07:29:58

标签: linux bash shell awk

在尝试优化我的服务器相关数据时,我和我的团队讨论了linux命令的用法。请求会员帮助我们更准确地理解这个概念。

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

简单的逻辑是将特定字段(带分隔符)awk到sort和uniq -c命令来计算此类实例的数量。

我可以看到两种方法来执行它:

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

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

文件大小可以用GB表示,这样哪个命令可以更有效。

3 个答案:

答案 0 :(得分:4)

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

  1. cat打开文件:

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

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

    awk '...' file
    
  4. 这些选择:

    1. 总是要避免,因为cat和管道正在使用资源并且没有提供任何价值,谷歌UUOC(无用的猫)以获取详细信息。
    2. 使用其他2个中的哪个是值得商榷的:

      1. 的优点是shell打开文件而不是工具,因此如果对所有工具执行此操作,则可以依赖一致的错误处理
      2. 的优点是该工具知道它正在操作的文件的名称(例如awk中的FILENAME),因此您可以在内部使用它。
      3. 要了解其中的差异,请考虑以下两个文件:

        $ 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消息不同,并且在各种awks中会有所不同。

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

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

        awk '...' file
        

        并针对您使用的特定问题:

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

答案 1 :(得分:3)

使用以下内容应该避免无用的cat

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

但我的建议是通过使用以下内容在sort中查找唯一项来避免昂贵的uniqawk命令:

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

这将打印唯一的行。

获得独特的数量:

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

答案 2 :(得分:1)

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

加快速度
cat one_file_name | some_command 

<one_file_name some_command

会更快,因为它会直接将one_file_name设置为stdin的{​​{1}}。

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