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].each
URLが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を使っているのなら、
- こちらの簡単な手順に従って、正規表現エンジンをオニグルマに更新してください。 http://oniguruma.rubyforge.org/
または
- 正規表現を交換してください。
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"]