【发布时间】:2014-07-19 00:38:06
【问题描述】:
我一直认为你不应该使用这样的范围表达式:
/start/,/end/
在 awk 中,因为尽管它使您只想打印匹配文本(包括开始行和结束行)的情况比替代方案略短*:
/start/{f=1} f{print; if (/end/) f=0}
当您想要稍微调整它以执行其他任何操作时,它需要完全重写或导致重复或其他不受欢迎的代码。例如如果您想使用上面的第二种形式打印不包括范围分隔符的匹配文本,您只需调整它以移动组件:
f{if (/end/) f=0; else print} /start/{f=1}
但如果您从 /start/,/end/ 开始,则需要放弃这种方法,转而支持我刚刚发布的内容,否则您必须编写如下内容:
/start/,/end/{ if (!/start|end/) print }
即复制不需要的条件。
然后我看到一个问题发布,需要识别文件中的 LAST end 以及解决方案中使用范围表达式的位置,我认为这似乎有一些价值(请参阅 https://stackoverflow.com/a/21145009/1745001)。
不过,现在,我又开始思考,完全不值得为范围表达式烦恼,而不使用范围表达式的解决方案同样适用于这种情况。
那么 - 有没有人举例说明范围表达式实际上为解决方案增加了显着的价值?
*我曾经使用过:
/start/{f=1} f; /end/{f=0}
但太多次我发现当f 为真并且/end/ 被发现时我必须做一些额外的事情(或者换句话说,只有在/end/ 被发现时才做某事如果f 是真的)所以现在我只是尝试坚持稍微不那么简短但更健壮和可扩展的:
/start/{f=1} f{print; if (/end/) f=0}
【问题讨论】:
-
我最近才了解范围表达式,我喜欢它们!当然,他们没有什么是“标志”变量无法做到的,但我认为它们是有用的。诚然,在使用
f时,您正在减少(一种)重复,但在这样做时,您有责任在记录之间跟踪f。这实际上意味着为了理解脚本,您必须(至少)阅读两次,而不是一次。 -
@TomFenech 您将如何处理增强脚本以不打印开始/结束行?扔掉原来的并从一个变量重新开始,或者在操作块或其他东西中使用
if引入开始/结束条件的重复?我对范围表达式的担忧是,如果/当您的要求发生变化时,恕我直言,没有合理的方法可以在此基础上进行构建。 -
我认为
if没有任何问题。这是两个正则表达式的简单组合,无论如何,这两种方法都不能很好地适应多种条件。我猜你可以做/start/ {getline; do { print; getline } while (!/end/)}如果你真的想要;) -
if的问题是您正在复制代码,因此如果您稍后必须测试不同的条件,那么您需要在 2 个地方进行相同的更改,这通常是不可取的在软件中。 wrtgetline建议 - 这充满了问题,不应实施,如果您正在考虑使用getline,请确保您阅读并完全理解 awk.info/?tip/getline。 -
我只是在开玩笑说使用
getline,但无论如何感谢链接:) 在避免重复方面,您始终可以将模式设置为变量并使用~运算符:$0~s, $0~e {if(!($0~s||$0~e)) print}文件`。无论如何,在我看来,所有的方法都是 hacky,所以每个人都有自己的想法。
标签: awk