2010-12-10 2 views

답변

92

Ruby CSV 라이브러리를 사용하면 필드 구분 기호를 지정할 수 있습니다. Ruby 1.9는 FasterCSV을 사용합니다. 이런 식으로 작동합니다 :

require "csv" 
parsed_file = CSV.read("path-to-file.csv", { :col_sep => "\t" }) 
+4

탭으로 구분 된 값 중 하나에 큰 따옴표가 포함되어 있으면이 방법이 실패합니다. 다른 대답의 StrictTsv 제안은 더욱 강력합니다. –

23

TSV에 대한 규칙은 실제로 CSV와는 조금 다릅니다. 가장 큰 차이점은 CSV는 쉼표를 필드 안에 넣은 다음 필드 안에 따옴표를 사용하고 따옴표를 이스케이프 처리하는 조항이 있다는 것입니다. 나는 간단한 응답이 실패하는 방법을 보여 빠른 예를 썼다 :

require 'csv' 
line = 'boogie\ttime\tis "now"' 
begin 
    line = CSV.parse_line(line, col_sep: "\t") 
    puts "parsed correctly" 
rescue CSV::MalformedCSVError 
    puts "failed to parse line" 
end 

begin 
    line = CSV.parse_line(line, col_sep: "\t", quote_char: "Ƃ") 
    puts "parsed correctly with random quote char" 
rescue CSV::MalformedCSVError 
    puts "failed to parse line with random quote char" 
end 

#Output: 
# failed to parse line 
# parsed correctly with random quote char 

당신은 당신이 볼 것으로 예상하지 않는 임의의 인용 문자를 사용 할 수있는 CSV 라이브러리를 사용하려면 파일 (예 쇼 경우 this). 그러나 필드 인용문에 대해 걱정할 필요없이 동일한 효과를 얻으려면 아래에 표시된 StrictTsv 클래스와 같은 간단한 방법을 사용할 수도 있습니다.

# The main parse method is mostly borrowed from a tweet by @JEG2 
class StrictTsv 
    attr_reader :filepath 
    def initialize(filepath) 
    @filepath = filepath 
    end 

    def parse 
    open(filepath) do |f| 
     headers = f.gets.strip.split("\t") 
     f.each do |line| 
     fields = Hash[headers.zip(line.split("\t"))] 
     yield fields 
     end 
    end 
    end 
end 

# Example Usage 
tsv = Vendor::StrictTsv.new("your_file.tsv") 
tsv.parse do |row| 
    puts row['named field'] 
end 

csv로 라이브러리 또는 더 엄격한 것을 사용의 선택은 당신에게 파일을 보내는 사람에 따라 달라집니다 그리고 그들은 엄격한 TSV 표준을 준수 할 것으로 예상되어 있는지. TSV를 표준에 대한

세부 내가 mmmries 대답을 좋아 http://en.wikipedia.org/wiki/Tab-separated_values

+0

외부 요령에 *가 아닌 * 코드 스 니펫을 포함하십시오. 그 요지는 이제 실망스러워 보이는데, 이는 정말 수치스러운 일입니다. –

+4

@JezenThomas가 머리를 가져 주셔서 감사합니다. 요지를 살펴 봐야하는 문제를 해결하기 위해 모든 코드 샘플을 인라인으로 뽑아 – mmmries

+0

훌륭한 대답입니다. . 나는 CSV 파서와 함께 끔찍하게'\ d'가 실패하는 것에 놀랐다. – dps

0

에서 찾을 수 있습니다. 그러나 루비가 분할의 끝에서 빈 값을 제거하는 방식이 싫다. 줄 바꿈 끝에 개행을 제거하지도 않습니다.

또한 필드 내에 잠재적 개행 문자가있는 파일이 있습니다.

def parse 
    open(filepath) do |f| 
    headers = f.gets.strip.split("\t") 
    f.each do |line| 
     myline=line 
     while myline.scan(/\t/).count != headers.count-1 
     myline+=f.gets 
     end 
     fields = Hash[headers.zip(myline.chomp.split("\t",headers.count))] 
     yield fields 
    end 
    end 
end 

이 데이터의 전체 라인을 취득하기 위해 필요한 모든 라인을 연결, 항상 (마지막에 잠재적 전무 항목없이) 데이터의 전체 집합을 반환 다음과 같이 그래서, 나는 그의 '구문 분석'을 다시 썼다.

관련 문제