【发布时间】:2015-11-25 11:19:21
【问题描述】:
我有一个包含汽车制造商列表的文件:
$ cat cars
subaru
mercedes
porche
ferrari
audi
mercedes
BMW
ferrari
toyota
lexus
mercedes
VW
$
我想打印mercedes 和ferrari 之间的所有行,因此所需的输出是:
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] 部分不能使用正则表达式。例如,如果我想同时使用mercedes 和mg-motors 作为开始标记,那么我不能使用[^m.*s] 正则表达式,因为它会匹配文字字符m、.。 * 和 s。
只有当第二个标记存在时,有没有更聪明的方法在两个标记之间打印带有sed 的文本?是否应该使用awk 来解决这个问题?
【问题讨论】:
-
你想要的输出没有意义。
-
sed 用于单个行的简单替换。如果您需要使用超过 s、g 和 p(带有 -n),那么您使用的工具是错误的,因为在 1970 年代中期,当 awk 被发明时,所有其他 sed 语言结构都已过时。此外,永远不要使用范围表达式,因为它们会使琐碎问题的解决方案变得非常简单,但是当问题变得更有趣时,就需要完全重写或复制条件。听起来您的问题出在雨天的情况下,但您的示例输入/输出只是晴天 - 请重新考虑!
标签: awk sed pattern-matching