如何在Ruby中使用范围正则表达式,类似于awk的/start/,/stop/?

4
我想做一个类似AWK的范围正则表达式,例如:
awk ' /hoststatus/,/\}/' file

在 AWK 中,这将打印文件中两个模式之间的所有行:
hoststatus {
host_name=myhost
modified_attributes=0
check_command=check-host-alive
check_period=24x7
notification_period=workhours
check_interval=5.000000
retry_interval=1.000000
event_handler=
}

我该如何在Ruby中实现这个功能?

附加题:你会如何在Python中实现它?

在AWK中这真的很强大,但我对Ruby还不熟悉,不确定该如何做。在Python中我也找不到解决方案。

2个回答

2

Ruby:

str =
"drdxrdx
hoststatus {
host_name=myhost
modified_attributes=0
check_command=check-host-alive
check_period=24x7
notification_period=workhours
check_interval=5.000000
retry_interval=1.000000
event_handler=
}"
str.each_line do |line|
  print line if line =~ /hoststatus/..line =~ /\}/
end

这是臭名昭著的触发器


@Tim Schaefer 这不是一个正则表达式,而是两个正则表达式相互切换作为活动表达式。据我所知,Ruby从Perl那里偷了这个技巧,Perl又从AWK那里偷了它。 - steenslag

1
使用Python时,通过向re传递multiline和dotall标志。在*后面加上?可以使其变为非贪婪模式。
>>> import re
>>> with open('test.x') as f:
...     print re.findall('^hoststatus.*?\n\}$', f.read(), re.DOTALL + re.MULTILINE)

基本上和我的一样,(但可能更好一点)。不过,这种方法的缺点是你会一次性读取整个文件,而不像我假设的那样逐行读取。 (我敢打赌awk也会更快:) - mgilson
@mgilson,同意。我所知道的唯一能够进行多行匹配并具有完整正则表达式功能的工具,而不仅仅是指定范围的能力,并且无需将整个文件加载到内存中的工具是pcregrep。 - iruvar
我无法让它工作。我已经尝试了很多变化,但仍然无法在Python中使其工作。不管怎样,还是谢谢... Tim - Tim Schaefer
@mgilson:性能取决于许多因素,例如,在文件中搜索IP的Python greps比awk更快(两个版本都不是为了速度而编写的)。不清楚re.findall()或awk的翻转闸门哪个更快(对于某些输入)。 - jfs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接