【问题标题】:Include header in the 'grep' result在“grep”结果中包含标题
【发布时间】:2012-10-06 21:13:45
【问题描述】:

有没有办法将'head -1'和'grep'命令组合成一个目录中的所有文件并将输出重定向到输出文件。我可以使用“sed”来做到这一点,但它似乎不如 grep 快。

sed -n '1p;/6330162/p' infile*.txt > outfile.txt

使用 grep 我可以一次执行以下一个文件:

head -1 infile1.txt;  grep -i '6330162' infile1.txt > outfile.txt

但是,我需要对目录中的所有文件执行此操作。插入通配符没有帮助,因为它首先打印标题,然后是 grep 输出。

【问题讨论】:

  • 当然不如grep快; grep 做得更少。

标签: shell grep


【解决方案1】:

我写了一个脚本hgrep来替换命令grep

#!/bin/bash

content=`cat`
echo "$content" | head -1
echo "$content" | tail -n+2 | grep "$@"

然后df -h | hgrep tmpfs将输出标题和行包括tmpfs

报价至关重要。

【讨论】:

    【解决方案2】:

    下面的意思是你只需要输入一次命令(而不是使用 && 并输入两次),也很容易理解。

    some-command | { head -1; grep some-stuff; }
    

    例如

    ps -ef | { head -1; grep python; }
    

    更新:这似乎只适用于ps,对不起,但我想这通常是人们想要的。

    如果您希望它适用于任意命令,似乎您必须编写一个迷你脚本,例如:

    #!/bin/bash
    
    first_line=true
    
    while read -r line; do
        if [ "${first_line}" = "true" ]; then
            echo "$line"
            first_line=false
        fi
        echo "$line" | grep $*
    done
    

    我将其命名为 hgrep.sh。然后你可以这样使用:

    ps -ef | ./hgrep.sh -i chrome
    

    这种方法的好处是我们使用grep,所以所有标志的工作方式完全相同。

    【讨论】:

    • 注意:这似乎适用于ps,但不适用于任何其他命令(df、ls、cat 等)。
    • @BrianPapantonio 是的,不知道为什么会这样,很奇怪。你知道为什么吗?
    • 经过进一步调查,我发现它适用于ps -e,但不适用于ps。显然ps -e 先发送标题行,然后不发送任何内容,然后缓冲输出的其余部分。 head 一定认为流在第一行之后就关闭了,所以它退出了,让 grep 看到剩下的。 tl;dr:这个技巧是偶然的。
    • @BrianPapantonio 更新了带有警告的答案。
    • 不是通用解决方案!我相信它只有在第一个命令在发送之前缓冲其整个输出(特定于应用程序并受缓冲区大小限制)时才有效,因为head -1 将在完成读取后发送 SIGPIPE,导致第一个命令停止。
    【解决方案3】:

    这将通过使用单个接收命令来工作:

    some-command | sed -n '1p;/PATTERN/p'
    

    使用多行标题也很容易:

    $ sudo netstat --tcp --udp --listening --numeric --program | sed --quiet '1,2p;/ssh/p'
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1258/sshd           
    tcp6       0      0 :::22                   :::*                    LISTEN      1258/sshd           
    

    reiterate,@samthebest 的解决方案仅适用于非常特定的情况;这将适用于任何写入标准输出的命令。

    【讨论】:

    • 我收到sed: illegal option -- -PATTERNgrepegrep 的工作方式相同吗?
    • sed有不同的版本;我已将其更改为使用更便携(但可读性较差)的标志。
    • 这可行且很有用,但问题要求“... in grep result”。我想重点可能是grepsed 更熟悉。例如,-ised 如何处理?
    • 您在最后一个 p 之前添加了一个 i。据我所知,该网站从不回避提出替代工具,因为限制回答者的选项会降低答案的质量,并且不太可能适用于其他人。
    • 是的,正如我所说的“这有效且有用”因此赞成。尽管如此,我仍然希望看到一个使用grep 的衬里。
    【解决方案4】:

    我会这样做的:

    ps -fe | awk '{ if ( tolower($0) ~ /network/ || NR == 1 ) print $0}' 
    

    【讨论】:

    • 这个 awk 过于复杂; awk 在左括号前使用谓词来过滤行。此外,print $0 单独存在时是多余的。这可以简化为ps -fe | awk 'NR == 1; /network/'
    【解决方案5】:

    您好,好奇您可以在您的 cmd 中使用 xargs。

    find /mahesh  -type f |xargs -I {} -t /bin/sh -c "head -1 {}>>/tmp/out.x|grep -i 6330162 {} >>/tmp/out.x"
    

    /mahesh 是您的文件所在的目录,输出放在 /tmp/out.x 中

    【讨论】:

      【解决方案6】:
      for file in *
      do
        [ "$file" = outfile.txt ] && continue
        head -n 1 "$file"
        grep -i '...' "$file"
      done > outfile.txt
      

      【讨论】:

      • 谢谢@Ignacio。我还添加了文件名以跟踪输出文件中数据的来源,因此添加了“文件”$file“;”。但是,在输出中,它附加了“ASCII 文本”,例如:file1.txt: ASCII text
      • 这是一个如此常见的用例,我很困惑为什么没有直接简单的解决方案
      猜你喜欢
      • 1970-01-01
      • 2017-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多