質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

4回答

1861閲覧

長文テキストから情報を取得したい

yuki_90453

総合スコア326

XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

1クリップ

投稿2017/02/06 09:25

編集2017/02/06 09:32

メール受信時に内容を解析し、情報を取得したいと考えています。メールはテキストメールでありHTML形式ではございません。
下記のメールから商品番号、サイズ、カラー、個数を取得したいと考えています。

(省略) --------------------------------------------------------------------- [受注番号] 000000-20170205-0000000 [日時] 2017-02-05 00:00:00 [注文者] 名前 太郎 (ナマエ タロウ) 様 〒123-0000 東京都 (TEL) 090-0000-4444 [支払方法] クレジット [ポイント利用] 1000 [配送方法] 郵便 [配送日時指定] [備考] ●備考 --------------------------------------------------------------------- [ショップ名] *********** ========== [送付先] 名前 太郎 (ナマエ タロウ) 様 〒123-0000 東京都 (TEL) 090-0000-4444 [商品] 商品名(商品番号) サイズ:XL カラー:ブルー ※オプション:無し 価格 6,0000(円) x 1(個) = 6,0000(円) (税込、送料込) 獲得ポイント660 ---------- 商品名(商品番号) サイズ:XL カラー:レッド ※オプション:無し 価格 6,0000(円) x 1(個) = 6,0000(円) (税込、送料込) 獲得ポイント660 ---------- 商品名(商品番号) サイズ:XL カラー:グリーン ※オプション:無し 価格 6,0000(円) x 1(個) = 6,0000(円) (税込、送料込) 獲得ポイント660 ********************************************************************* 小計 18,0000(円) 送料 0(円) 離島・一部地域では別途料金が必要な場合があります --------------------------------------------------- 合計 18,0000(円) --------------------------------------------------------------------- 今回のお買い物で獲得するポイント 660 --------------------------------------------------------------------- *消費税について 消費税率 8% 消費税計算順序 1商品毎に消費税計算 1円未満消費税端数 切り捨て --------------------------------------------------------------------- (省略)

##質問
正規表現では複数行や、ここ〜ここまでといった指定方法が難しいかと思います。
正規表現以外の方法でかんたんに取得する方法はないでしょうか?

###備考
使用言語 Ruby
メールの容量は5,6KBぐらいの量になります。
送信者側のフォーマットは決まっておりますので、受信者側で解析、変換したいと考えております。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

a.rb

ruby

1FILE_NAME = 'data.txt' 2START_ITEM = 1 3IN_ITEM = 2 4SEP_ITEM = 3 5END_ITEM = 0 6 7def parse_file(file_name) 8 lines = File.readlines(file_name) 9 parse_lines(lines) 10end 11 12def parse_lines(lines) 13 items = [] 14 status = nil 15 item_block = [] 16 lines.each do |line| 17 status = stat_machine(line.chomp, status) 18 if status == SEP_ITEM || status == END_ITEM 19 items << parse_block(item_block) 20 item_block = [] 21 elsif status == IN_ITEM 22 item_block << line 23 end 24 end 25 items 26end 27 28def stat_machine(line, status) 29 if status.nil? 30 return START_ITEM if line == '[商品]' 31 elsif status == START_ITEM || status == IN_ITEM || status == SEP_ITEM 32 return SEP_ITEM if line == '----------' 33 return END_ITEM if line == '*********************************************************************' 34 return IN_ITEM 35 end 36 nil 37end 38 39def parse_block(item_block) 40 headers = item_block[0].match(/(.*)\((.*)\)/) 41 size = color = option = price = count = point = nil 42 item_block.shift 43 item_block.each do |line| 44 size = line.match(/サイズ:(.*)/)[1] if line.start_with?('サイズ:') 45 color = line.match(/カラー:(.*)/)[1] if line.start_with?('カラー:') 46 option = line.match(/※オプション:(.*)/)[1] if line.start_with?('※オプション:') 47 price, count = line.gsub(',', '').match(/価格 (\d+)\(円\) x (\d+)\(個\) = (\d+)\(円\)/).captures if line.start_with?('価格') 48 point = line.match(/獲得ポイント(\d*)/)[1] if line.start_with?('獲得ポイント') 49 end 50 51 { 52 name: headers[1], 53 code: headers[2], 54 size: size, 55 color: color, 56 price: price.to_i, 57 count: count.to_i, 58 option: option, 59 point: point.to_i 60 } 61end 62 63items = parse_file(FILE_NAME) 64items.each { |item| puts item }

data.txt

(省略) --------------------------------------------------------------------- [受注番号] 000000-20170205-0000000 [日時] 2017-02-05 00:00:00 [注文者] 名前 太郎 (ナマエ タロウ) 様 〒123-0000 東京都 (TEL) 090-0000-4444 [支払方法] クレジット [ポイント利用] 1000 [配送方法] 郵便 [配送日時指定] [備考] ●備考 --------------------------------------------------------------------- [ショップ名] *********** ========== [送付先] 名前 太郎 (ナマエ タロウ) 様 〒123-0000 東京都 (TEL) 090-0000-4444 [商品] 商品A(000-1234) サイズ:XL カラー:ブルー ※オプション:無し 価格 6,0000(円) x 1(個) = 6,0000(円) (税込、送料込) 獲得ポイント660 ---------- 商品A(001-1234) サイズ:XL カラー:レッド ※オプション:無し 価格 6,0000(円) x 1(個) = 6,0000(円) (税込、送料込) 獲得ポイント660 ---------- 商品A(002-1234) サイズ:XL カラー:グリーン ※オプション:無し 価格 6,0000(円) x 1(個) = 6,0000(円) (税込、送料込) 獲得ポイント660 ********************************************************************* 小計 18,0000(円) 送料 0(円) 離島・一部地域では別途料金が必要な場合があります --------------------------------------------------- 合計 18,0000(円) --------------------------------------------------------------------- 今回のお買い物で獲得するポイント 660 --------------------------------------------------------------------- *消費税について 消費税率 8% 消費税計算順序 1商品毎に消費税計算 1円未満消費税端数 切り捨て --------------------------------------------------------------------- (省略)

実行結果

$ ruby a.rb {:name=>"商品A", :code=>"000-1234", :size=>"XL", :color=>"ブルー", :price=>60000, :count=>1, :option=>"無し", :point=>660} {:name=>"商品A", :code=>"001-1234", :size=>"XL", :color=>"レッド", :price=>60000, :count=>1, :option=>"無し", :point=>660} {:name=>"商品A", :code=>"002-1234", :size=>"XL", :color=>"グリーン", :price=>60000, :count=>1, :option=>"無し", :point=>660}

投稿2017/02/07 14:07

編集2017/02/08 22:05
katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

別に複雑な正規表現を使う必要は無く、「見出しが含まれる」くらいでいいです。
1行ずつ読みながら、見出しがあればそこからデータを取得します。
ぜんぜん難しくも、面倒でもないです。簡単です。

投稿2017/02/06 09:35

otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuki_90453

2017/02/06 09:59

each_lineというのがあると知りませんでした、取り急ぎありがとうございます。
guest

0

Ruby

1#encoding : utf-8 2mail = open("メールテスト.txt", &:read).encode("UTF-8").scan(%r|商品名(.+)\nサイズ(.+)\nカラー(.+)\n※オプション:(.+)\n価格(.+)\n|) 3mail = mail.transpose 4item = mail[0] 5size = mail[1] 6color = mail[2] 7num = mail[4] 8mail.clear 9item.map!{|e| e.gsub(/\(|\)/, "")} 10size.map!{|e| e.gsub(":", "")} 11color.map!{|e| e.gsub(":", "")} 12num.map!{|e| e.scan(%r|\d+?\(個\)|).map{|ee| ee.gsub("(個)", "")}}.flatten! 13mail << item 14mail << size 15mail << color 16mail << num 17mail = mail.transpose 18mail.each do |element| 19 puts "#{element[0]}\s#{element[1]}\s#{element[2]}\s#{element[3]}" 20end

実行結果例

Ruby

1商品番号 XL ブルー 1 2商品番号 XL レッド 1 3商品番号 XL グリーン 1

今更ですが考えてみました。
正規表現以外の方法でという質問でしたが正規表現でもここからここまで
みたいなことができるのではと考えた次第です。
openとreadでテキストファイル全体を読み込んで正規表現で該当する部分を抜き出します。
transposeでそれぞれの項目ごとにまとめて、形を整えます。
形を整えたら再びtransposeで商品ごとにして出力します。

投稿2017/02/06 10:44

編集2017/02/06 11:24
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuki_90453

2017/02/06 13:31

助かります、ありがとうございます。
guest

0

ベストアンサー

プログラムは示せませんが戦略だけ書いておきます。

基本的には1行ずつ処理することになると思います。
その行にキーワードが含まれていれば解析することで対応することになるでしょう。

サイズとカラーは固定の文字列のようなので、行に含まれていればコロン(:)以降の文字列を取得すれば出来ますが、商品番号は「商品名」が都度変わると思うのでちょっと面倒ですね。商品名のリストを持っておいて比較しても良いかもしれませんが、リストが膨大だったり不定期に更新されたりするとそれに対応する必要があるので処理が面倒になります。
もし、

商品名:実際の商品名(商品番号)

と固定の文字列(商品名:)が頭に必ず入るのならサイズやカラーと同じになるので楽なんですけどね。

それと、個数は価格のところにしか無いようなので、価格を含む行を探して、「x」から「(個)」の間の数字を取ってくることで対応できるかと。

投稿2017/02/06 09:48

PineMatsu

総合スコア3579

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuki_90453

2017/02/06 09:59

each_lineというのがあると知りませんでした、取り急ぎありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問