ruby 中是否有可用的函数,可以返回正则表达式匹配后的部分?



我有一个字符串说它采用以下格式。

2020/07/08 16:30:03.919 263825 (Followed by strings)
2020/07/08 16:30:03.919 263826 (Followed by strings)

我们是否有一个函数来仅返回(后跟字符串)部分。如果我们有第一部分的模式

^w*s*(?<time_var>w*/w*/w*sw*:w*:w*.w*)sw*

上述模式与时间戳后跟数字匹配。 我在 Ruby 中的第一个 = 符号之后找到了这个 Get 子字符串,但实际上并没有帮助!我在这里做错了什么吗?

irb(main):001:0> line = "2020/07/08 16:30:03.919 263825 (Followed by strings)"
=> "2020/07/08 16:30:03.919 263825 (Followed by strings)"
irb(main):002:0> line.partition('^w*s*(?<time_var>w*/w*/w*sw*:w*:w*.w*)sw*').last
=> ""
irb(main):003:0> line.partition('^w*s*(?<time_var>w*/w*/w*sw*:w*:w*.w*)sw*')
=> ["2020/07/08 16:30:03.919 263825 (Followed by strings)", "", ""]

如果没有最后一个函数,它匹配整个字符串?

MatchData#post_match在实际匹配后返回字符串:

pattern = /^w*s*(?<time_var>w*/w*/w*sw*:w*:w*.w*)sw*/
line = "2020/07/08 16:30:03.919 263825 (Followed by strings)"
line.match(pattern, &:post_match)
#=> " (Followed by strings)"

你可以试试:

line = "2020/07/08 16:30:03.919 263825 (Followed by strings)"
l = line.gsub(/^w*s*(?<time_var>w*/w*/w*sw*:w*:w*.w*)sw*/, "").lstrip
# l ==> "(Followed by strings)"

您可以使用正则表达式捕获:

str = <<~STR
2020/07/08 16:30:03.919 263825 (Followed by strings)
2020/07/08 16:30:03.919 263826 (Followed by strings)
STR
tstamp_line_rgx = %r{d{4}/dd/dd dd:dd:dd.d{3} d+ (.*)}
str.lines.map do |line|
line[tstamp_line_rgx, 1]
end

我有一个稍微不同的正则表达式(我认为你的也可能有效),但重要的部分是(.*),它捕获"时间戳 + pid 之后的任何内容,直到行尾",并且它被1引用string_variable[regex, 1],因为它是1第一个括号捕获组。

当"直接"使用它时,您可以更清楚地看到正则表达式捕获组等(与string[regex, capture_num]语法相反):

[12] pry(main)> a_string = "2020/07/08 16:30:03.919 263826 (Followed by strings)"
=> "2020/07/08 16:30:03.919 263826 (Followed by strings)"
[13] pry(main)> tstamp_line_rgx.match(a_string)
=> #<MatchData "2020/07/08 16:30:03.919 263826 (Followed by strings)" 1:"(Followed by strings)">

您可以使用K在正则表达式之后对字符串进行keep 操作:

regex = %r(^w*s*(?<time_var>w*/w*/w*sw*:w*:w*.w*)sw*)
'2020/07/08 16:30:03.919 263825 (Followed by strings)'.match(/#{regex}K.*/).to_s
# => " (Followed by strings)"

您的时间戳具有非常明确的模式。除其他外,

'2020/07/08 16:30:03.919 263825'.size
#=> 30

因此,可以这样写:

str = '2020/07/08 16:30:03.919 263825 the cat and the hat'
time_stamp = str[0,30]
#=> "2020/07/08 16:30:03.919 263825" 
remainder  = str[30..-1].strip
#=> "the cat and the hat"

如果您希望通过确认它是有效的时间戳来确保安全,您可以执行以下操作。

time_stamp_str = time_stamp[0,23]
#=> "2020/07/08 16:30:03.919" 
time_stamp_supp = time_stamp[23..-1]
#=> " 263825" 
time_stamp_supp.match?(/A d+z/)
#=> true
require 'time'
def time_stamp_valid?(time_stamp_str)
rv = DateTime.strptime(time_stamp_str, '%Y/%m/%d %H:%M:%S.%L') rescue false
!!rv
end
time_stamp_valid?(time_stamp_str)
#=> true

这里

rv #=> #<DateTime: 2020-07-08T16:30:03+00:00 ((2459039j,59403s,919000000n),+0s,2299161j)>

请参阅 DateTime::strptime 和 (有关格式化指令) DateTime#strftime。 如果字符串不表示有效日期,strptime引发异常,在这种情况下,time_stamp_valid?内联拯救异常并返回false

!!只是将对象(这里为DateTime对象)转换为true,并将虚假对象(nilfalse)转换为false

以这种方式验证时间戳比使用正则表达式更可取,因为正则表达式可能会给出不正确的结果。例如,大多数正则表达式无法确定 2000 年 2 月 29 日是否为有效日期(尽管可以这样做)。此外,这种方法比制作一个正则表达式要容易得多,正则表达式只能很好地评估日期时间刺痛的正确性。

最重要的是,不要使用parse,因为它可能是非常不可预测的。例如:DateTime.parse("She thought that maybe he was the killer after all") #=> #<DateTime: 2020-05-01T00:00:00+00:00 ((2458971j,0s,0n),+0s,2299161j)>.

最新更新