我正在尝试编写一个ruby脚本,该脚本将在其他两个字符串之间返回文本。问题是两个匹配的字符串包含特殊字符。转义特殊字符不能解决问题。
我尝试转义特殊字符,不同的匹配模式,并为匹配的字符串提供变量,但运气不佳。
我还通过仅使用 ODS 和 NAME 作为分隔符来测试了简化匹配。那似乎行得通。
####Example contents of logfile
#### 'aaaaaaaaa ODS | Filename = /tmp/bbbbbb | NAME = ccccc'
log_to_scan = 'logfile'
marker1 = 'ODS | FILENAME = /tmp/'
marker2 = ' | NAME'
contents = File.read(log_to_scan)
print contents.match(/ODS \| FILENAME = \/tmp\/(.*) \| NAME/m[1].strip
print contents.match(/marker1(.*)marker2/m)[1].strip
鉴于上面的示例内容,我希望输出为bbbbbb。但是,我什么也没收到或出现了NoMethod错误。不知道还有什么是真的,或者我做错了什么。
答案 0 :(得分:3)
str = 'aaaaaaaaa ODS | Filename = /tmp/bbbbbb | NAME = ccccc'
marker1 = 'ODS | FILENAME = /tmp/'
marker2 = ' | NAME'
r = /(?<=#{Regexp.escape(marker1)}).*(?=#{Regexp.escape(marker2)})/i
#=> /(?<=ODS\ \|\ FILENAME\ =\ \/tmp\/).*(?=\ \|\ NAME)/i
str[r]
#=> "bbbbbb"
或
r = /#{Regexp.escape(marker1)}(.*)#{Regexp.escape(marker2)}/i
str[r,1]
#=> "bbbbbb"
,或者,如果已知要匹配的字符串是小写字母,或者允许将该字符串小写返回:
s = str.downcase
#=> "aaaaaaaaa ods | filename = /tmp/bbbbbb | name = ccccc"
m1 = marker1.downcase
#=> "ods | filename = /tmp/"
m2 = marker2.downcase
#=> " | name"
id1 = s.index(m1) + m1.size
#=> 32
id2 = s.index(m2, id1+1) - 1
#=> 37
str[id1..id2]
#=> "bbbbbb"
请参见Regexp::escape。在#1中,
(?<=#{Regexp.escape(marker1)})
是正后方,要求marker1
出现在比赛之前。
(?=#{Regexp.escape(marker2)})
是正向超前,要求marker2
立即关注比赛。
在#3中,我使用了String#index的形式,该形式带有第二个参数(“偏移”)。
答案 1 :(得分:2)
您的原始表达式很好,如果您的字符串输入中可能还有其他空格,并且可以正常工作,我们会在这里稍作修改:
^.+?ODS(\s+)?\|(\s+)?FILENAME(\s+)?=(\s+)?\/tmp\/(.+?)(\s+)?\|(\s+)?NAME(\s+)?=(\s+)?(.+?)$
,我们期望的输出位于这两个捕获组中:
(.+?)
re = /^.+?ODS(\s+)?\|(\s+)?FILENAME(\s+)?=(\s+)?\/tmp\/(.+?)(\s+)?\|(\s+)?NAME(\s+)?=(\s+)?(.+?)$/mi
str = 'aaaaaaaaa ODS | Filename = /tmp/bbbbbb | NAME = ccccc'
# Print the match result
str.scan(re) do |match|
puts match.to_s
end
答案 2 :(得分:1)
String#scanf
怎么样?
> require 'scanf'
> str = 'ODS | FILENAME = /tmp/ | NAME'
> str.scanf('ODS | FILENAME = %s | NAME')
=> ["/tmp/"]