我一直争辩说你永远不应该使用范围表达式,如:
/start/,/end/
Run Code Online (Sandbox Code Playgroud)
在awk中,因为虽然它只是简单的情况,你只想打印匹配的文本,包括起始和结束线比替代*更简洁:
/start/{f=1} f{print; if (/end/) f=0}
Run Code Online (Sandbox Code Playgroud)
当你想稍微调整它以做任何其他事情时,它需要完全重写或导致重复或其他不需要的代码.例如,如果您想使用上面的第二个表单打印除范围分隔符之外的匹配文本,您只需调整它以移动组件:
f{if (/end/) f=0; else print} /start/{f=1}
Run Code Online (Sandbox Code Playgroud)
但是如果你从一开始/start/,/end/就需要放弃那种方法来支持我刚发布的内容,或者你必须写下这样的内容:
/start/,/end/{ if (!/start|end/) print }
Run Code Online (Sandbox Code Playgroud)
即重复不希望的条件.
然后我看到一个问题,要求end在文件中识别LAST ,并在解决方案中使用范围表达式,我认为这似乎有一些价值(请参阅/sf/answers/1480150661/).
但现在,我又回想起根本不值得使用范围表达式,并且不使用范围表达式的解决方案也适用于该情况.
那么 - 有没有人有一个例子,其中范围表达式实际上为解决方案增加了显着的价值?
*我以前用过:
/start/{f=1} f; /end/{f=0}
Run Code Online (Sandbox Code Playgroud)
但是很多次我发现我必须做一些额外的事情,当它f是真的并且/end/被发现时(或者换一种方式只做一些事情,如果/end/发现IF f是真的那么)所以现在我只是试着坚持稍微不那么简短但更多强大且可扩展:
/start/{f=1} f{print; if (/end/) f=0}
Run Code Online (Sandbox Code Playgroud)
Scr*_*zer 12
有趣.我也经常从范围表达式开始,然后切换到使用变量..
我认为这种情况可能有用,除了纯粹的仅限范围的情况之外,如果你想打印一个匹配,但只有它在一定范围内.还因为它立即显而易见.例如:
awk '/start/,/end/{if(/ppp/)print}' file
Run Code Online (Sandbox Code Playgroud)
有了这个输入:
start
dfgd gd
ppp 1
gfdg
fd gfd
end
ppp 2
ppp 3
start
ppp 4
ppp 5
end
ppp 6
ppp 7
gfdgdgd
Run Code Online (Sandbox Code Playgroud)
将产生:
ppp 1
ppp 4
ppp 5
Run Code Online (Sandbox Code Playgroud)
- 当然也可以使用:
awk '/start/{f=1} /ppp/ && f; /end/{f=0}' file
Run Code Online (Sandbox Code Playgroud)
但它更长,可读性更低..
虽然您认为/start/,/end/范围表达式可以很容易地用条件重新实现,但它有许多有趣的用例,可以单独使用它。正如您所观察到的,它对于处理表格数据可能没有什么价值,这是awk的主要但不仅仅是用例。
那么 - 有没有人有一个例子,其中范围表达式实际上为解决方案增加了显着的价值?
在提到的用例中,范围表达式提高了易读性。下面是一些示例,其中范围表达式准确地选择了要处理的文本。这些只是一些示例,但类似的应用程序有无数,展示了awk令人难以置信的多功能性。
假设每个日志行都以 ISO 时间戳开头,下面的过滤器将选择给定 1 小时范围内的所有事件:
awk '/^2015-06-30T12:00:00Z/,/^2015-06-30T13:00:00Z/'
Run Code Online (Sandbox Code Playgroud)
awk '/---- begin file.data ----/,/---- end file.data ----/'
Run Code Online (Sandbox Code Playgroud)
这可用于将资源与 shell 脚本(使用cat)捆绑在一起,提取部分 GPG 签名消息(使用 准备--clearsign)或更一般的 MIME 消息。
范围模式可用于匹配 LaTeX 环境,因此例如我们可以选择目录中所有文章的摘要:
awk '/begin{abstract}/,/end{abstract}/' *.tex
Run Code Online (Sandbox Code Playgroud)
或者所有的定理,准备一个定理数据库!
awk '/begin{theorem}/,/end{theorem}/' *.tex
Run Code Online (Sandbox Code Playgroud)
或者编写一个linter确保定理不包含引用(如果我们认为这是不好的风格):
awk '
/begin{theorem}/,/end{theorem}/ { if(/\\cite{/) { c+= 1 } }
END { printf("There were %d bad-style citations.\n", c) }
'
Run Code Online (Sandbox Code Playgroud)
或预处理表等。