/ / RubyでのTXTファイルの抽出に関する問題 - ruby​​-on-rails、ruby

ruby-ruby-on-rails、rubyにおけるTXTファイルの抽出に関する問題

TXT形式のデータファイルがあります。以下のルビコードを使用してTXTファイルからURLフィールドを解析します。

f = File.open(txt_file, "r")
f.each_line { |line|
rows = line.split(",")
rows[3].each do |url|
next if url=="URL"
puts url
end
}

TXTは含まれています:

name,option,price,URL
"x", "0,0,0,0,0,0", "123.40","http://domain.com/xym.jpg"
"x", "0,0,0,0,0,0", "111.34","http://domain.com/yum.jpg"

出力:

0

出力がオプションフィールド "0,0,0,0,0,0"から来るのはなぜですか?これをスキップしてURLフィールドを取得する方法

環境 ルビ1.8.7 レール2.3.8 宝石1.3.7

回答:

回答№1は2

これを簡単にするために、CSV解析ツールをチェックします。

 require "rubygems"
require "faster_csv"

FasterCSV.foreach(txt_file, :quote_char => """,
:col_sep =>",", :row_sep =>:auto) do |row|
puts row[3] if row[3] != "URL"
break
end

また、私はあなたが「どのように誤解していると思います」 split() うまくいくでしょう。走れば split() あなたのファイルからの1行に対して、あなたは "の配列を取り戻そうとしています columns その単一行に対して、多次元配列ではありません。 rows[3].each 提案するだろう。


回答№2の場合は1

EDIT:読む前に、私はJeff Swensenによる答えに完全に同意します。

私はあなたの内側のループが何のためにあるのか完全にはわかりません((rows[3].eachURLが1つしかない場合は、1行を「行」に変換できないためです。 ** 文字を入力してURLの配列を返しますが、それでも余分な二重引用符を削除する必要があります。そうしないと、正規表現を使用できます。

#!/usr/bin/env ruby

f = DATA
urls = f.readlines.map do |line|
line[/([^"]+)"**/, 1]
end
urls.compact!

p urls

__END__
name ,option,price, **URL**
"x", "0,0,0,0,0,0", "123.40",**"http://domain.com/xym.jpg"**
"x", "0,0,0,0,0,0", "111.34",**"http://domain.com/yum.jpg"**

への呼び出し compact なぜなら、 map 挿入します nil その表現に一致しない何かをヒットしたときにオブジェクト String#[] メソッド、参照してください ここに


回答№3の場合は1

"0"が結果である理由はあなたのCSV形式(列の値全体が引用符で囲まれている場合は列の値に区切り文字が含まれる可能性があります)を解析することを期待している場合、コードはコンマ文字に盲目的に分割されます。Rsvy1.9を使用している場合.2、その後、あなたはすでにへのアクセス権を持っているでしょう FasterCSV としょうかん。


回答№4の場合は1

必要なフィールドが常に二重引用符で囲まれていることが確実な場合は、抽出の基礎としてカンマではなくそれを使用できます。

File.open(txt_file) do |f|
f.each_line do |l|
cols = l.scan(/(?<!\)"(.*?)(?<!\)"/)
cols[3].tap{|url| puts url if url}
end
end
  • あなたのコードでは、開かれたIOは閉じられていません。これは悪い習慣です。ブロックを閉じることを忘れないように、ブロックを使用することをお勧めします。
  • 二つ (?<!\)" 正規表現では、エスケープされていない二重引用符と一致します。彼らはネガティブルックバックを使用しています。
  • .*? これは、一致がエスケープされていない二重引用符を超えないようにします。
  • tap 繰り返しを避けるためです cols[3] 2回の操作 puts そして if.

もう一度編集する

あなたがruby 1.8.7を使っているのなら、

または

  • 正規表現を交換してください。 tap また使用することはできません。代わりに以下を使用してください。

.

File.open(txt_file) do |f|
f.each_line do |l|
cols = l.scan(/(?:A|[^\])"(.*?[^\]|)"/)
url = cols[3]
puts url if url
end
end

オニグルマを使ってお勧めします。これは、ruby 1.9以降に導入された新しい正規表現エンジンで、ruby 1.8で使用されていたものよりもはるかに強力で高速です。それはruby 1.8に簡単にインストールできます。


回答№5の場合は0

データはCSV形式ですが、やりたいことが 最終 文字列内のフィールドは、それからちょうどそれをする:

text =<<EOT
name,option,price,URL
"x", "0,0,0,0,0,0", "123.40","http://domain.com/xym.jpg"
"x", "0,0,0,0,0,0", "111.34","http://domain.com/yum.jpg"
EOT

require "pp"
text.lines.map{ |l| l.split(",").last }

二重引用符と末尾の改行を整理したい場合は、次のようにします。

text.lines.map{ |l| l.split(",").last.gsub(""", "").chomp }
# => ["URL", "http://domain.com/xym.jpg", "http://domain.com/yum.jpg"]