【问题标题】:Print all lines between "start" and "end" if and only if the target pattern "target" occurs between "start" and "end"当且仅当目标模式 \"target\" 出现在 \"start\" 和 \"end\" 之间时,打印 \"start\" 和 \"end\" 之间的所有行
【发布时间】:2023-01-31 21:21:47
【问题描述】:

我想使用 linux shell 搜索目录中的所有文件,并查看任何文件中的行,这些行的目标模式介于已知的开始和结束模式之间。例如,给定

blah blah
blah blah blah
blah start blah
blah
target
blah blah
end blah
blah 
blah

我想回来

blah start blah
blah
target
blah blah
end blah

我努力了

sed -n '/start/,/end/{/target/p}' file.txt

它只搜索一个文件并且似乎没有打印从开始到结束的整个时间间隔。我用 grep 和 awk 失败了(可能反映了我缺乏经验)。

非常感谢。

【问题讨论】:

    标签: linux


    【解决方案1】:

    有不同的方法可以做到这一点。如果不安装一些额外的软件,我会建议使用 Perl,因为它可能已经安装在您的系统上。

    perl -0ne 'print $& if /^[^
    ]*?start.*?target.*?end.*?$/ms' file.txt
    

    Demo这里。

    '-0' 命令行开关基本上使 perl 将整个文本文件作为一行读取(它将行分隔符设置为代码为 0 的字符,而不是正常的 ' ').

    使用'-n'开关perl执行表达式,为输入的每一行指定'-e'开关,默认情况下不打印结果。

    所以,这个单行代码就像这个伪代码一样工作:

    set line separator to byte 0, in practice gobble the whole text file at once;
    while (there are some lines to read from the input) {
       read the line;
       if (line matches the regex /^[^
    ]*?start.*?target.*?end.*?$/ms) {
          print the whole match;
       }
    }
    

    【讨论】:

    • 嗨,非常感谢。它似乎确实适用于上面的示例。但是,假设单个文本文件中有多个此类间隔,它似乎无法正确返回所有此类间隔。看起来它可能只抓住了第一个。我会帮助理解您的 perl 调用的语法。 (较小的问题:它不会递归检查 - 或者至少是批量检查 - 一堆文本文件。)。
    • 我已经更新了答案,以便它可以捕获多个间隔。我只加了'?'在两个地方使正则表达式寻找最小匹配,而不是最大匹配。
    猜你喜欢
    • 1970-01-01
    • 2018-01-23
    • 2019-07-06
    • 1970-01-01
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    • 2021-07-04
    • 2017-10-29
    相关资源
    最近更新 更多