ruby - 如何编写能够匹配一两行文本的正则表达式

标签 ruby regex

我尝试匹配一些可以是一行或两行的文本。我希望能够有效地处理这两种情况。文本字符串的格式将保持一致,并且包含多个选项卡。我正在尝试用 ruby 进行匹配。正文如下:

单行:

#3  Hello Stormy    Scratched - Reason Unavailable                           11:10 AM ET 

两行:

#3  Hello Stormy    Scratched - Reason Unavailable                            11:10 AM ET   
                    Scratch Reason - Reason Unavailable changed to Trainer     2:19 PM ET  

我必须在此处使用空格来格式化字符串,但实际文本使用制表符来分隔各个部分:数字和名称、划痕和原因以及时间。

示例输出:

一行:#3 你好,Stormy Scratched - 原因不可用,东部时间上午 11:10

两行 #3 Hello Stormy Scratched - Reason Unavailable 更改为 Trainer 2:19PM

注意:理想情况下,两行输出将包括第一行的编号和名称。

我能够构建一个匹配各个部分的表达式,但是选项卡、第二行以及在两行输出上包含数字和马名的要求给我带来了麻烦。

最佳答案

您不需要花哨的正则表达式来完成您想要的操作,您只需要知道如何去做。

Ruby 的 Enumerable 有一个名为 slice_before 的方法它采用正则表达式,用于确定数组中的哪些元素被分组在一起。 Array 继承自 Enumerable。例如:

text = '#3  Hello Stormy    Scratched   -   Reason Unavailable          11:10 AM ET
#3  Hello Stormy    Scratched   -   Reason Unavailable          11:10 AM ET
                        Scratch Reason  -   Reason Unavailable changed to Trainer   2:19 PM ET
'

data = text.split("\n").slice_before(/\A\S/).to_a

require 'pp'
pp data

输出:

[["#3\tHello Stormy\tScratched\t-\tReason Unavailable\t\t\t11:10 AM ET"],
["#3\tHello Stormy\tScratched\t-\tReason Unavailable\t\t\t11:10 AM ET",
  "\t\t\tScratch\tReason\t-\tReason Unavailable changed to Trainer\t2:19 PM ET"]]

换句话说,通过分割 "\n" 上的文本创建的数组按不以空格开头的行进行分组,即模式 /\A\S/ 。所有单行都位于单独的子数组中。前一行的延续行与该行分组。

如果您正在从磁盘读取文件,则可以使用IO.readlines将文件作为数组读取,避免了分割文件的需要。

如果需要,您可以进一步处理该数组,以重建行和延续行,使用类似以下内容:

data = text.split("\n").slice_before(/\A\S/).map{ |i| i.join("\n") }

哪个变成data进入:

["#3\tHello Stormy\tScratched\t-\tReason Unavailable\t\t\t11:10 AM ET",
"#3\tHello Stormy\tScratched\t-\tReason Unavailable\t\t\t11:10 AM ET\n\t\t\tScratch\tReason\t-\tReason Unavailable changed to Trainer\t2:19 PM ET"]

如果您需要将每一行拆分为其组成字段,请使用 split("\t") 。如何跨子数组执行此操作留给您作为练习,但我会涉及 map .


编辑:

...I like your solution, but I'm getting undefined method for slice_before.

试试这个:

require 'pp'
require 'rubygems'

class Array

  unless Array.respond_to?(:slice_before)
    def slice_before(pat)
      result = []
      temp_result = []
      self.each do |i|

        if (temp_result.empty?)
          temp_result << i
          next
        end

        if i[pat]
          result << temp_result
          temp_result = []
        end

        temp_result << i
      end
      result << temp_result

    end
  end

end

调用:

ary = [
  '#3  Hello Stormy    Scratched - Reason Unavailable                           11:10 AM ET',
  '#3  Hello Stormy    Scratched - Reason Unavailable                            11:10 AM ET',
  '                    Scratch Reason - Reason Unavailable changed to Trainer     2:19 PM ET',
]

pp ary.slice_before(/\A\S/)

看起来像:

[
  ["#3  Hello Stormy    Scratched - Reason Unavailable                           11:10 AM ET"],
  ["#3  Hello Stormy    Scratched - Reason Unavailable                            11:10 AM ET",
   "                    Scratch Reason - Reason Unavailable changed to Trainer     2:19 PM ET"]
]

关于ruby - 如何编写能够匹配一两行文本的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14947905/

相关文章:

ruby-on-rails - 显示评分最高的对象。 Letsrate,Rails

python正则表达式匹配确切的词

php - 检查字符串是否以 php 中的特定单词结尾?

python - python 和 regex 模块如何处理反斜杠?

javascript - 使用正则表达式删除带有省略号的未完成字符串

正则表达式重复 aa,bb,cc

xml - 用于转换结构的 XSLT + 用于转换值的 Ruby?

ruby-on-rails - 如何在 Rails 的同一模型中调用自类方法?

java - 从字符串中删除多余的零

ruby-on-rails - 我如何解决 "Missing host to link to! Please provide the :host parameter"? (返回率)