【问题标题】:get specific lines in a range pattern from a text file从文本文件中获取范围模式中的特定行
【发布时间】:2013-06-25 11:29:26
【问题描述】:

我正在尝试搜索文本文件的特定部分并将信息保存在两个关键字之间。允许我只保存中间信息的语法是什么样的?目前我的代码是:

$awk -f strip.awk <in>out
{
Strip.awk

{
if ($0 == "<!-- start of lyrics -->")
    lyr = 1
    if ($0=="<!-- end of lyrics -->")
    lyr = 0
    if(lyr==1)
    Lyrics = lyr $0
    }
printf("%s/n", Lyrics)
>>Lyric.csv

}

【问题讨论】:

    标签: regex perl sed awk pattern-matching


    【解决方案1】:

    这个脚本应该这样做:

    #!/bin/sh
    
    awk '
    /<!-- start of lyrics -->/ { lyrics = 1; next }
    /<!-- end of lyrics -->/ { exit }
    lyrics { print }
    '
    

    如果你称它为script.sh,那么你可以这样使用它:

    ./script.sh < input.txt > lyrics.txt
    

    这就是它的工作原理:

    • /&lt;!-- start of lyrics --&gt;/ { lyrics = 1; next } :如果该行与开始“模式”匹配,则设置lyrics 变量并跳转到下一行
    • /&lt;!-- end of lyrics --&gt;/ { exit } :如果该行匹配结束“模式”,则退出
    • lyrics { print } :如果设置了 lyrics 变量,则打印该行

    【讨论】:

      【解决方案2】:

      “仅保存中间的信息”是什么意思并不完全清楚,但假设您的意思是只想打印两个分隔符之间的内容:

      awk '/<!-- start of lyrics -->/{p=1}/<!-- end of lyrics -->{p=0}p{print}0' input.txt
      

      应该可以工作。

      它基本上根据是否看到开始/结束标签来设置和重置一个标志,并且只在标志非零时打印行。

      【讨论】:

        【解决方案3】:
        awk '/<!-- start of lyrics -->/,/<!-- end of lyrics -->/' input.txt >> Lyric.csv
        

        这是我的"The AWK Programming Language" (1984, p23)副本:

        • 模式 1 ,模式 2 { statements }
          范围模式匹配从模式 1 匹配的行到模式 2 匹配的下一行的每个输入行,包括在内;语句在每次匹配时执行

          范围模式不能属于 任何其他模式。

        从输出范围中排除pattern 1 & pattern 2

        awk  '/pattern 1/,/pattern 2/ {if ($0 !~ /pattern 1|pattern 2/) print}' input.txt
        

        【讨论】:

        • 嘿,这真的很酷。我不知道在我的“AWK 编程语言”副本中错过了多少次。 +1让我睁开眼睛。我必须将它放在一个文件中才能运行它(shell 解释错误?),它在输出中包含“开始”和“结束”行。
        • @n0741337 添加了一些解释。
        • @captcha 排除您可以将其缩短为的模式 - awk 'NR==1,/pattern 1/{next}/pattern 2/,0{next}1'
        • @captcha - 感谢您提供额外信息。我有 1988 年修订版,其中“范围模式”部分从第 32 页开始,文字略有不同。
        • @JS웃 您的代码只能找到文件中的第一个范围,而不是更多。
        【解决方案4】:

        sedawk 都支持 regex ranges

        $ cat ff
        1
        2
        3
        4
        START
        4
        5
        3
        6
        7
        END
        14
        5
        8
        

        $ awk '/START/,/END/' ff
        START
        4
        5
        3
        6
        7
        END
        

        $ sed -n '/START/,/END/p' ff
        START
        4
        5
        3
        6
        7
        END
        

        【讨论】:

          猜你喜欢
          • 2013-06-26
          • 2013-06-20
          • 2021-11-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-24
          相关资源
          最近更新 更多