【问题标题】:How to "grep" out specific line ranges of a file如何“grep”出文件的特定行范围
【发布时间】:2010-05-26 15:09:59
【问题描述】:

很多时候我会grep -n 任何文件来找到我正在寻找的东西。说输出是:

1234: whatev 1
5555: whatev 2
6643: whatev 3

如果我想然后只提取 1234 和 5555 之间的行,有没有工具可以做到这一点?对于静态文件,我有一个脚本,它对文件执行wc -l,然后进行数学运算以将其与尾部和头部分开,但对于不断写入的日志文件,这并不能很好地工作。

【问题讨论】:

标签: command-line grep


【解决方案1】:

尝试使用上面提到的 sed http://linuxcommando.blogspot.com/2008/03/using-sed-to-extract-lines-in-text-file.html。例如使用

sed '2,4!d' somefile.txt

somefile.txt 的第二行打印到第四行。 (别忘了查看http://www.grymoire.com/Unix/Sed.html,sed 是一个很棒的工具。)

【讨论】:

  • 一个有用的后续信息是如何将行号添加到 sed 结果中...像这样通过管道将其输入 nl:sed ''"$start"','"$end"'!d' somefile.txt | nl -ba -v$start
  • @Scorchio !d 是什么意思?
  • @ManuelJordan d 是 sed 的删除命令。 ! 反转限制(即在这种情况下,指定范围)。所以2,4!d 意味着删除除第 2-4 行之外的所有内容。
  • @Scorchio 感谢您的解释。 - 通常! 在开头 - 类似于!2,4d
【解决方案2】:

以下命令将执行您在 someFile 中要求“提取 1234 和 5555 之间的行”的操作。

sed -n '1234,5555p' someFile

【讨论】:

  • 我必须添加 / 分隔符才能使其工作:sed -n '/1234/,/5555/p' someFile
  • 小东西,但你不需要引号
【解决方案3】:

如果我理解正确,您想在两个行号之间找到一个模式。 awk 单线可以是

awk '/whatev/ && NR >= 1234 && NR <= 5555' file

您无需运行 grep 后跟 sed

Perl 单行:

perl -ne 'if (/whatev/ && $. >= 1234 && $. <= 5555) {print}' file

【讨论】:

    【解决方案4】:

    如果你能保证你想要的位置,行号是可以的。多年来,我最喜欢的口味是这样的:

    sed "/First Line of Text/,/Last Line of Text/d" filename
    

    删除从第一个匹配行到最后一个匹配的所有行,包括那些行。

    使用带有“p”而不是“d”的 sed -n 来打印这些行。对我来说更有用,因为我通常不知道这些线在哪里。

    【讨论】:

      【解决方案5】:

      把它放在一个文件中并使其可执行:

      #!/usr/bin/env bash
      start=`grep -n $1 < $3 | head -n1 | cut -d: -f1; exit ${PIPESTATUS[0]}`
      if [ ${PIPESTATUS[0]} -ne 0 ]; then
          echo "couldn't find start pattern!" 1>&2
          exit 1
      fi
      stop=`tail -n +$start < $3 | grep -n $2 | head -n1 | cut -d: -f1; exit ${PIPESTATUS[1]}`
      if [ ${PIPESTATUS[0]} -ne 0 ]; then
          echo "couldn't find end pattern!" 1>&2
          exit 1
      fi
      
      stop=$(( $stop + $start - 1))
      
      sed "$start,$stop!d" < $3
      

      使用参数执行文件(注意脚本不处理参数中的空格!):

      1. 开始 grep 模式
      2. 停止 grep 模式
      3. 文件路径

      要与您的示例一起使用,请使用参数:1234 5555 myfile.txt

      包括带有开始和停止模式的行。

      【讨论】:

        【解决方案6】:

        如果你想要行而不是行范围,你可以用 perl 来做:例如。如果您想从文件中获取第 1、3 和 5 行,例如 /etc/passwd:

        perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd
        

        【讨论】:

        • 仅供参考,$l 是“dollar el”而不是“dollar one”。一个更糟糕(即更短)的命令是perl -ne 'if($.~~[1,3,5]){print}' /etc/passwd
        【解决方案7】:

        如果我想然后只提取 1234 和 5555 之间的行,是 有这样的工具吗?

        还有ugrep,这是一个与 GNU/BSD grep 兼容的工具,但它提供了一个带有一系列行号的 -K 选项(或 --range)来做到这一点:

        ugrep -K1234,5555 -n '' somefile.log
        

        您可以使用常用的 GNU/BSD grep 选项和正则表达式模式(但它还提供更多,例如 -K。)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-02-26
          • 1970-01-01
          • 2013-02-15
          • 1970-01-01
          • 1970-01-01
          • 2013-08-14
          • 1970-01-01
          相关资源
          最近更新 更多