2010-03-09 4 views
3

TSV 형식의 파일 (탭으로 구분 된 값)을 구문 분석해야합니다. 정규식을 사용하여 파일을 각 줄로 나누지 만 각 줄을 구문 분석 할 때 만족스러운 파일을 찾을 수는 없습니다.TSV 파일을 구문 분석하십시오.

(?<g>("[^"]+")+|[^\t]+) 

하지만 줄에 항목이 2 개 이상 연속 따옴표가있는 경우 작동하지 않습니다 : 은 지금 나는이 왔어요.

파일 형식은 다음과 같습니다. 각 요소는 표로 구분됩니다. 항목에 탭이 있으면 큰 따옴표로 묶습니다. 항목에 큰 따옴표가 포함되어 있으면 두 배가됩니다. 그러나 때로는 요소가 4 개의 이중 인용 부호를 포함하고, 위의 정규 표현식은 요소를 두 개의 다른 것으로 분리합니다.

예 :

"항목", "2", "OK"

올바르게 2 개 요소로 파싱 item1ok : item1ok항목 "2"OK (불필요한 따옴표를 다듬은 후에) :

,515,

item1oK "항목" "" "2oK"

3 개 요소로 해석된다 , 항목 item1ok"2ok (다시 트리밍 후).

누구나 정규식을이 케이스에 맞게 만드는 방법에 대한 아이디어가 있습니까? 아니면 단순히 TSV를 파싱 할 다른 솔루션이 있습니까? (나는 C#에서 이것을하고있다).

답변

7

TextFieldParser을 사용할 수 있습니다. 이것은 기술적으로 VB 어셈블리이지만 Microsoft.VisualBasic.FileIO 어셈블리를 참조하여 C#에서도 사용할 수 있습니다.

위 링크의 예는 탭으로 구분 된 파일에서도 사용하고 있습니다.

+2

+1 .Net 프레임 워크의 일부입니다. Microsoft에서 지원하며 별도의 배치가 필요하지 않습니다. – MarkJ

+0

Dotnet Core와 Dotnet Standard에서는 VisualBasic 코드가 오픈 소스가 아니며 포팅되지 않기 때문에 사용할 수 없습니다. – ppumkin

0

RegEx를 사용하는 대신 String.Split Method (Char[]) 메서드를 사용해보십시오.

+1

사항 String.split을 (전 C# 모르지만이 (파이썬에서) 트릭을 할해야합니다. – Antoine

+0

저장 버튼을 누르 자마자 생각했습니다. 내가 뭐라 할 수 있니? 알아, 나는 빨아. – DaveB

6

자신의 CSV/TSV 파일 파서 (또는 String.Split)를 작성하는 대신 "Fast CSV Reader"또는 "FileHelpers library"을 사용하는 것이 좋습니다.

저는 첫 번째 문자를 사용하고있어 매우 만족합니다 (예 : 쉼표, 세미콜론, 탭과 같은 구분 문자를 지원합니다).

+0

저는 Lumenworks CSV 리더기를 사용해 보았는데 잘 작동하고 TSV 판독기의 기초가 될 것입니다. – Lazarus

+0

+1 FileHelpers에 대해! 우수한 라이브러리. –

+0

그건 분명히 좋은 해결책이지만, .net 클래스 대답이 내 필요에 더 잘 맞도록 내 코드에 대한 추가 종속성을 피하고 싶습니다. – Antoine

-1

가 정확하지 그래서뿐만 아니라 구분 기호로 쌌다 도표화를 고려할 것)

txt = 'item1ok\t"item""2""oK"\titem1oK\t"item""""2oK"\tsomething else' 
regex = ''' 
(?:     # definition of a field 
"((?:[^"]|"")*)" # either a double quoted field (allowing consecutive "") 
|     # or 
([^"]*)   # any character except a double quote 
)      # end of field 
(?:$|\t)    # each field followed by a tab (except the last one) 
''' 
r = re.compile(regex, re.X) 
# now find each match, and replace "" by " and remove trailing \t 
# remove also the latest entry in the list (empty string) 
columns = [t[0].replace('""', '"') if t[0] != '' else t[1].strip() for t in r.findall(txt)][:-1] 
print columns 
# prints: ['item1ok', 'item"2"oK', 'item1oK', 'item""2oK', 'something else'] 
+1

질문은 특히 C#을위한 것이 었습니다. 다른 언어로 솔루션을 게시하는 것은 도움이되지 않습니다. – kevinc

관련 문제