尝试从不同行连接字符串时如何避免出现“ nil”错误

时间:2019-01-31 22:48:15

标签: ruby

我有一个像这样的文件:

QWWWQV27

ETYUM
2019-01-29 03:20:07  
KJJD_990 

RP04MMB High risk YUZZP 

HHLPPD  
2019-01-23 12:34:13  
CDF55UHM11  

UYRP566_I Low risk ABCX

我想将日期和包含单词"risk"的下一行连接起来,并将其分配给变量。

我有以下代码。

require 'date'

File.foreach("file.txt",sep="\n") do |line|
    if (DateTime.strptime(line.strip, '%Y-%m-%d %H:%M:%S') rescue nil)
     date = line.strip  #Here I'm storing the date in variable "date"
     next
    end

    risk = line[/.*risk.*/]
    next unless not (risk.nil?)
    output = date + risk
    p output
end

我收到此错误:

NoMethodError: undefined method `+' for nil:NilClass
        from (irb):3333:in `block in irb_binding'
        from (irb):3325:in `foreach'
        from (irb):3325
        from /usr/bin/irb:11:in `<main>'

当我捕获包含"risk"的行并将其与存储在变量date中的日期连接起来时,此变量的内容为nil

我不知道何时date更改为nil。我究竟做错了什么?包含单词"risk"的行出现后,如何存储日期以将其串联起来?

1 个答案:

答案 0 :(得分:1)

str =<<_
QWWWQV27

ETYUM
2019-01-29 03:20:07  
KJJD_990 

RP04MMB High risk YUZZP 

HHLPPD  
2019-01-23 12:34:13  
CDF55UHM11  

UYRP566_I Low risk ABCX
_

FNAME = 'temp'
File.write(FNAME, str)
  #=> 144

require 'date'

我们首先定义两个proc,这两个proc都有一个参数line,它将是文件line.strip!之后的一行。

date_r = Proc.new { |line| DateTime.strptime(line,
  '%Y-%m-%d %H:%M:%S') rescue false }
  #=> #<Proc:0x00005784561a3b28@(irb):567> 
risk_r = Proc.new { |line| line.match? /\brisk\b/i }
  #=> #<Proc:0x00005784561c5610@(irb):569> 

接下来,使用Array#cycle生成一个枚举数enum。每次执行p = enum.next时,两个过程date_rrisk_r中的一个将分配给变量p,首先分配给变量date_r,然后分配给risk_r ,然后是date_r等等,直到永远。这两个过程都返回truefalse

enum = [date_r, risk_r].cycle
  #=> #<Enumerator: [#<Proc:0x00005784561a3b28@(irb):567>,
    #<Proc:0x00005784561c5610@(irb):569>]:cycle> 
p = enum.next # initialize p to date_r
  #=> #<Proc:0x00005784561a3b28@(irb):567> 

File.foreach(FNAME).with_object([]) do |line, arr|
  line.strip!
  if p.call(line)
    arr << line
    p = enum.next
  end
end.each_slice(2).map(&:join)
  #=> ["2019-01-29 03:20:07RP04MMB High risk YUZZP",
  #    "2019-01-23 12:34:13UYRP566_I Low risk ABCX"]

请注意,在执行.each_slice(2).map(&:join)之前,

File.foreach(FNAME).with_object([]) do |line, arr|
  ...
end
  #=> ["2019-01-29 03:20:07", "RP04MMB High risk YUZZP",
  #    "2019-01-23 12:34:13", "UYRP566_I Low risk ABCX"]