2

1行または2行のテキストを一致させようとしています。両方のシナリオを効率的に処理できるようにしたいと思います。テキスト文字列は一貫してフォーマットされ、いくつかのタブが含まれます。私はルビーで試合をしようとしています。テキストは次のとおりです。

単線:

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

2行:

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

ここでは文字列をフォーマットするためにスペースを使用する必要がありましたが、実際のテキストではタブを使用してさまざまなセクション(番号と名前、傷と理由と時間)を区切ります。

サンプル出力:

1行:#3 HelloStormyScratched-理由利用不可11:10AMET

2行#3 HelloStormyScratched-理由利用不可がトレーナー2:19PMに変更されました

注:理想的には、2行の出力には、最初の行の番号と名前が含まれます。

さまざまなセクションに一致する式を作成することはできますが、タブ、2行目、および2行の出力に番号と馬の名前を含める必要があるために問題が発生します。

4

3 に答える 3

2

やりたいことをするのに派手な正規表現は必要ありません。それをどうやってやるのかを知る必要があります。

RubyのEnumerableにはslice_before、配列内のどの要素がグループ化されているかを判別するために使用される正規表現をとるというメソッドがあります。配列はそれを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ます。


編集:

...私はあなたのソリューションが好きですが、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"]
]
于 2013-02-19T05:23:56.023 に答える
1

'#'文字が文字列の他の場所に表示されないと想定できる場合は、かなり単純化されます。次に、このようなものがそれを行う必要があります:

 /^#[^#]*/m

もう1つのより一般的なアプローチは、#で始まる最初の行と、その後のスペースまたはタブで始まる行を一致させることです。

 /^#.*?$(\n^[ \t].*?$)*/m

行が常に#で始まるとは限らない場合は、[^ \t](スペースやタブではなく)に置き換えることができます。

于 2013-02-19T02:05:45.640 に答える
1

REで楽しい!これはハッキーですが、そこにはいくつかの異なるタイプのマッチング戦略があります。

# Two-line example
s = <<-EOS
  #3\tHello Stormy\t\tScratched - Reason Unavailable\t\t\t11:10 AM ET\t
  \t\t\tScratch Reason - Reason Unavailable changed to Trainer\t2:19 PM ET
EOS
# allow leading/trailing whitespace, get the number, name, last reason and time
s =~ /\A\s*(#\d)\t+([^\t]+)(?:\t+.*)?(?:\t+(.*))\t+(\d+:\d+ (?:AM|PM) ET)\s*\Z/m
# ["#3", "Hello Stormy", "Scratch Reason - Reason Unavailable changed to Trainer", "2:19 PM ET"]
a = $1, $2, $3, $4

注:これは、一致する文字列内の1つのメッセージのみを想定しています。
注:1行の場合はテストされていません:)

于 2013-02-19T02:40:23.913 に答える