【问题标题】:print text between two markers with sed if second marker exists如果存在第二个标记,则使用 sed 在两个标记之间打印文本
【发布时间】:2015-11-25 11:19:21
【问题描述】:

我有一个包含汽车制造商列表的文件:

$ cat cars
subaru
mercedes
porche
ferrari
audi
mercedes
BMW
ferrari
toyota
lexus
mercedes
VW
$ 

我想打印mercedesferrari 之间的所有行,因此所需的输出是:

mercedes
porche
ferrari
mercedes
BMW
ferrari

我的第一个想法是使用gsed -n '/mercedes/,/ferrari/p' cars,但这显然不起作用,因为sed 逐行处理文件,并且无法知道此文件中的最后一个mercedes 后面没有ferrari .我可以使用 gsed -n '/mercedes/h;/^[^mercedes].*$/H;/ferrari/{g;p}' cars 完成此操作,但我发现此解决方案几乎没有问题:

1) 如果结束标记存在,但开始标记不存在。例如,如果我文件中的最后一个mercedes 替换为ferrari,则输出错误。

2) 在[^mercedes] 部分不能使用正则表达式。例如,如果我想同时使用mercedesmg-motors 作为开始标记,那么我不能使用[^m.*s] 正则表达式,因为它会匹配文字字符m.*s

只有当第二个标记存在时,有没有更聪明的方法在两个标记之间打印带有sed 的文本?是否应该使用awk 来解决这个问题?

【问题讨论】:

  • 你想要的输出没有意义。
  • sed 用于单个行的简单替换。如果您需要使用超过 s、g 和 p(带有 -n),那么您使用的工具是错误的,因为在 1970 年代中期,当 awk 被发明时,所有其他 sed 语言结构都已过时。此外,永远不要使用范围表达式,因为它们会使琐碎问题的解决方案变得非常简单,但是当问题变得更有趣时,就需要完全重写或复制条件。听起来您的问题出在雨天的情况下,但您的示例输入/输出只是晴天 - 请重新考虑!

标签: awk sed pattern-matching


【解决方案1】:
awk 'a{a=a"\n"$0}/mercedes/{a=$0}/ferrari/{print a;a=""}' file
mercedes
porche
ferrari
mercedes
BMW
ferrari



sed -n '/mercedes/{:a;N;/ferrari/{p;b};ba}' file
mercedes
porche
ferrari
mercedes
BMW
ferrari

【讨论】:

    【解决方案2】:

    您可以浏览该文件两次:

    • 第一次算你有多少ferrari
    • 第二次在mercedes 之后和ferrari 之前打印这些行,以防仍有一些ferrari 出现:

    即:

    awk 'FNR==NR{if ($0~/ferrari/) {ferr++}; next}
         /mercedes/{flag=1}
         flag && count<ferr
         /ferrari/{flag=0; count++}' file file
    

    How to select lines between two marker patterns which may occur multiple times with awk/sed中的进一步解释。

    测试

    $ awk 'FNR==NR{if ($0~/ferrari/) {ferr++}; next} /mercedes/{flag=1} flag && count<ferr; /ferrari/{flag=0; count++}' a a
    mercedes
    porche
    ferrari
    mercedes
    BMW
    ferrari
    

    【讨论】:

      【解决方案3】:

      这可能对你有用(GNU sed):

      sed -n '/mercedes/!d;:a;/ferrari/p;//d;N;ba' file
      

      使用 seds 类似 grep 的命令开关 -n 仅在请求时打印。删除除包含mercedes 之外的所有行,然后打印包含ferrari 的模式空间并将其删除。否则追加下一行并再次测试。

      【讨论】:

        猜你喜欢
        • 2014-11-13
        • 1970-01-01
        • 2011-11-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-29
        • 2015-05-17
        • 2020-12-18
        相关资源
        最近更新 更多