【问题标题】:Extract lines between two line numbers in shell在shell中提取两个行号之间的行
【发布时间】:2014-03-12 15:29:34
【问题描述】:

如何在 shell 中使用 sed 或任何其他过滤器

假设我在两个变量 $line1$line2 中有两个特定的行号,我想像这样提取这两行之间的行

cat my_file_path | command $line1 $line2

如果我的文件是:

1:bbb

2:cccc

3:dddd

4:eeeee

如果我这样做,我的输出应该是:

cat my_file_path | command 1 3

输出

bbb
cccc

【问题讨论】:

    标签: bash shell sed


    【解决方案1】:

    使用 sed:

    $ cat my_file_path | sed -n "${line1},${line2}p"
    

    或者,甚至更好(cat 有点多余):

    $ sed -n "${line1},${line2}p" my_file_path
    

    【讨论】:

    • 这个答案不正确,因为 OP 不希望打印行 $line1, $line2
    • sed 地址范围是包容性的,不是排斥性的,所以你的答案是错误的。
    【解决方案2】:

    你可以使用有尾有头的管道

    tail -n +$line1 | head -n $((line2-line1))
    

    【讨论】:

    • 像魅力一样工作。您需要定义 line1 和 line2,例如:line1=499,但这正是我所需要的。
    • 我喜欢!非常干净,不依赖 sed 或 awk
    【解决方案3】:

    未经测试:

    awk -v s="$line1" -v e="$line2" 'NR>s&&NR<e' file
    

    你可以用&gt;= or &lt;=控制“包含/独占”

    如果您想让 shell var 中的前导/尾随空格安全:

     awk -v s="$line1" -v e="$line2" 'NR>1*s&&NR<1*e' file
    

    【讨论】:

      【解决方案4】:

      这是我在 Centos 上使用的,此示例从 myFile.log

      打印 100 到 200 之间的行
       awk 'NR >= 100 && NR <= 200' myFile.log
      

      100 之前的其他示例行

      awk  'NR <= 100' fileName.log
      

      请注意,您也可以使用 >,

      这个答案使用 NR 变量又名记录号,如行号,用于更复杂的场景您可以查看 AWK 内置变量:https://www.thegeekstuff.com/2010/01/8-powerful-awk-built-in-variables-fs-ofs-rs-ors-nr-nf-filename-fnr/

      希望对你有帮助

      【讨论】:

        【解决方案5】:

        使用 sed 打印(仅!)100 和 200 之间的行:

        sed '1,100d;200,$d' file
        

        优化:遇到范围结束时退出。

        sed -n '1,100b;200q;p' file
        

        优化使用b命令:

        b——无条件分支(即:总是跳转到一个标签,跳过 或重复其他命令,而不重新开始新的循环)

        [...] 如果省略标签,分支命令将重新开始循环。

        GNU sed manual: branching and flow control

        测试优化是否有效。

        seq 1 100000 > file # A file with 10,000 lines
        echo
        echo "Without optimization:"
        time sed '1,100d;200,$d' file >/dev/null
        echo
        echo "With optimization:"
        time sed -n '1,100b;200q;p' file >/dev/null
        

        输出:

        Without optimization:
        
        real  0m0.004s
        user  0m0.003s
        sys   0m0.001s
        
        With optimization:
        
        real  0m0.001s
        user  0m0.000s
        sys   0m0.001s
        

        【讨论】:

          【解决方案6】:

          使用 awk:

          打印第 100 到 200 行(含):

          awk 'NR==100, NR==200' myfile.log
          

          优化:打印完所需范围的最后一行后退出:

          awk 'NR==100, NR==200; NR==200 {exit}' myfile.log
          

          使用了一个范围模式

          范围模式由两个用逗号分隔的模式组成,格式为“begpat, endpat”。用于匹配连续输入记录的范围。
          https://www.gnu.org/software/gawk/manual/html_node/Ranges.html

          模式可以是正则表达式模式表达式模式。以上使用表达式模式与NR做比较。

          2021-03-09 更新:我刚刚意识到 OP 希望它是一个独家系列。这样就可以了:

          awk 'NR==200{p=0};p;NR==100{p=1}' myfile.log
          

          优化:打印完所需范围的最后一行后退出:

          awk 'NR==200{exit};p;NR==100{p=1}' myfile.log
          

          测试优化是否有效:

          seq 1 100000 > file # A file with 10,000 lines
          echo
          echo "Without optimization:"
          time awk 'NR==200{p=0};p;NR==100{p=1}' file > /dev/null
          echo
          echo "With optimization:"
          time awk 'NR==200{exit};p;NR==100{p=1}' file > /dev/null
          

          输出:

          Without optimization:
          
          real  0m0.014s
          user  0m0.013s
          sys   0m0.001s
          
          With optimizaton:
          
          real  0m0.002s
          user  0m0.001s
          sys   0m0.001s
          

          【讨论】:

            【解决方案7】:

            不是确切的答案,但对于进行一些手动日志文件调查并希望在不费力和行计算的情况下提取大量行的任何人都可能有用,尤其是在涉及tail -f 时。试试less the-big-log-file.log

            • 打开文件,转到起始位置(例如使用/2021-11-21 19:00 搜索)。
            • 用命令mM标记当前位置
            • 然后转到结束位置,例如/2021-11-23 23:00 搜索。
            • 使用以下命令提取标记点和结束位置之间的线以分隔文件:|Mtee log-excerpt.txt

            您会在当前目录中找到 log-excerpt.txt,所有行都位于两个搜索结果位置之间。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-12-15
              • 2010-11-15
              • 2018-02-13
              • 2016-01-19
              • 1970-01-01
              相关资源
              最近更新 更多