【问题标题】:Linux using grep to print the file name and first n charactersLinux 使用 grep 打印文件名和前 n 个字符
【发布时间】:2010-09-27 06:57:35
【问题描述】:

如何使用 grep 执行搜索,当找到匹配项时,将打印文件名以及该文件中的前 n 个字符?注意n是可以指定的参数,与前n个字符是否实际包含匹配字符串无关。

【问题讨论】:

    标签: linux grep


    【解决方案1】:

    您需要将 grep 的输出通过管道传输到 sed 以完成您想要的操作。这是一个例子:

    grep mypattern *.txt | sed 's/^\([^:]*:.......\).*/\1/'
    

    点数是要打印的字符数。许多版本的 sed 通常提供一个选项,例如 -r (GNU/Linux) 和 -E (FreeBSD),允许您使用现代风格的正则表达式。这样就可以用数字指定要打印的字符数。

    N=7
    grep mypattern *.txt /dev/null | sed -r "s/^([^:]*:.{$N}).*/\1/"
    

    请注意,此解决方案比其他人提出的调用多个进程的解决方案要高效得多。

    【讨论】:

    • 在我的 linux 机器上,sed 不接受 -E(grep 可以)。但是它确实适用于 -r
    • 他正在寻找文件的前 N ​​个字符,而不是 N 个匹配的字符。此外,在其中添加 /dev/null 以防 *.txt 评估为 0 或 1 个文件。例如。 grep mypattern *.txt /dev/null | sed ...
    • 我给出的扩展 RE 模式不会匹配少于 N 个字符的行,因此这些将根据规范正确打印。您对添加 /dev/null 参数的需求是正确的。
    【解决方案2】:

    很少有工具可以打印“n 个字符”而不是“n 行”。你确定你真的想要字符而不是线条吗?整个事情可能最好在 Perl 中完成。按照说明(使用grep),我们可以这样做:

    pattern="$1"
    shift
    n="$2"
    shift
    grep -l "$pattern" "$@" |
    while read file
    do
        echo "$file:" $(dd if="$file" count=${n}c)
    done
    

    $file 周围的引号正确地保留了文件名中的多个空格。我们可以讨论一下命令行的用法,目前(假设命令名是'ngrep'):

     ngrep pattern n [file ...]
    

    我注意到@litb 使用了'head -c $n';这比我使用的dd 命令更简洁。可能有些系统没有head(但它们很陈旧)。我注意到head的POSIX版本只支持-n和行数; -c 选项可能是 GNU 扩展。

    【讨论】:

      【解决方案3】:
      grep -l pattern *.txt | 
          while read line; do 
              echo -n "$line: "; 
              head -c $n "$line"; 
              echo; 
           done
      

      如果您想查看前n 行而不是字节,请将-c 更改为-n

      【讨论】:

        【解决方案4】:

        这里有两个想法:

        1) 如果效率不是问题(这种情况永远不会发生),您可以在对每个文件运行 grep 后检查 $status [csh]。例如:(对于 N 个字符 = 25。)

        foreach FILE ( file1 file2 ... fileN )
          grep targetToMatch  ${FILE} > /dev/null
          if ( $status == 0 ) then
             echo -n "${FILE}:  "
             head -c25 ${FILE}
          endif
        end
        

        2) GNU [FSF] head 包含一个 --verbose [-v] 开关。它还提供 --null,以容纳带有空格的文件名。还有 '--',用来处理像 "-c" 这样的文件名。所以你可以这样做:

        grep --null -l targetToMatch -- file1 file2 ... fileN |
        xargs --null head -v -c25 --
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-24
          • 2021-12-09
          • 2022-12-24
          • 2015-02-15
          • 2013-03-14
          • 2010-10-07
          相关资源
          最近更新 更多