2010-02-12 4 views
2

사실상 UNIX passwd 파일 형식 인 쉼표 구분자 인 이스케이프 문자 \을 구문 분석하려고합니다 (이스케이프 문자는 \이므로 문자 그대로 이스케이프 처리해야 함). 나는 이것을 위해 정규 표현식을 사용하려고 노력하고 있지만 Lookahead/Lookbehind 어설 션을 위해 Oniguruma를 사용할 때조차도 간략히 설명하고 있습니다. 기본적으로구분 된 텍스트를 이스케이프 문자로 구문 분석

, 다음의 모든 작업을해야합니다 :

a,b,c # => ["a", "b", "c"] 
\a,b\,c # => ["a", "b,c"] 
a,b,c\ 
d  # => ["a", "b", "c\nd"] 
a,b\\\,C# => ["a", "b\,c"] 

어떤 아이디어가?

첫 번째 응답이 매우 양호하게 보입니다.

\a,,b\\\,c\,d,e\\f,\\,\ 
g 

포함하는 파일로는 제공 : 아주 가까운

[["\\a,"], [","], ["b\\\\\\,c\\,d,"], ["e\\\\f,"], ["\\\\,"], ["\\\ng\n"], [""]] 

합니다. 모든 것이 쉼표로 올바르게 분리되는 한이 첫 번째 패스에서 이스케이프 처리를 수행 할 필요가 없습니다. 나는 (훨씬 더) Oniguruma을 시도하여 결국 : 나는 CSV 클래스 시도를 줘야 할 것

Oniguruma::ORegexp.new(%{ 
    (?:  # - begins with (but doesn't capture) 
    (?<=\A) # - start of line 
    |  # - (or) 
    (?<=,) # - a comma 
) 

    (?:   # - contains (but doesn't capture) 
    .*?   # - any set of characters 
    [^\\\\]? # - not ending in a slash 
    (\\\\\\\\)* # - followed by an even number of slashes 
)*? 

    (?:  # - ends with (but doesn't capture) 
    (?=\Z) # - end of line 
    |  # - (or) 
    (?=,)) # - a comma 
    }, 

    'mx' 
).scan(s) 

답변

3

는 시도이 :

s.scan(/((?:\\.|[^,])*,?)/m) 

그것은 '아무튼 \ 다음에 오는 문자를 번역하지만 나중에 별도의 단계로 수행 할 수 있습니다.

+0

아주 좋았지 만, 이스케이프 된 문자를 OP가 원하는대로 리터럴 문자로 변경하지 않습니다. 아마도 정규 표현식에서 수행 할 수 없습니다. –

+0

이 수정은 효과가 있으며 후행 쉼표 자체는 캡처하지 않는다고 생각합니다. s.scan (/ ((? : \\. | [^]) *),?/m) –

+0

s.scan/(? : \\. | [^,]) *) [, \ n $]/mx는 좀 더 강건 해 보입니다. –

2

.

그리고 정규식 솔루션 (해킹?) 다음과 같습니다 출력을 생성합니다

#!/usr/bin/ruby -w 

# contents of test.csv: 
# a,b,c 
# \a,b\,c 
# a,b,c\ 
# d 
# a,b\\\,c 

file = File.new("test.csv", "r") 
tokens = file.read.scan(/(?:\\.|[^,\r\n])*|\r?\n/m) 
puts "-----------" 
tokens.length.times do |i| 
    if tokens[i] == "\n" or tokens[i] == "\r\n" 
    puts "-----------" 
    else 
    puts ">" + tokens[i] + "<" 
    end 
end 
file.close 

:

----------- 
>a< 
>b< 
>c< 
----------- 
>\a< 
>b\,c< 
----------- 
>a< 
>b< 
>c\ 
d< 
----------- 
>a< 
>b\\\,c< 
----------- 
+0

옳은 방향으로 곁눈질하다면 CSV처럼 보일 것입니다. 당연히 아니지만, 운이 좋으면'csv' 라이브러리를 설득 할 수 있습니다. –

+0

CSV 클래스가 너무 느려서 불행하게도 필요한 부분이 없습니다. –

+0

정규식 솔루션이 (CSV) 파서보다 느릴 것이라고 확신합니다. –

관련 문제