2009-11-13 4 views
-1

\n이 이미 즉시 \r에 의해 앞서는 경우가 아니면 \n의 모든 어커런스를 \r\n으로 바꾸는 정규 표현식을 작성하려고했습니다. 내가 노력 있도록 regexps '에 뒤에 보면 지원하지 않는 루비 1.8.6이 일을 해요 :이 정규 표현식이 인접 줄 바꿈과 일치하지 않는 이유는 무엇입니까?

\r\n\r\n사이의 기존 \r\n로 대체 할 One\n\nTwo\r\nThree 의도가 \n\n 위해이었다 문자열을 감안할 때
# try to replace \n proceeded by anything other than \r with \r\n 
str.gsub(/([^\r])\n/, "\\1\r\n") # \\1 is the captured character to be kept 

은 수정하지 않아야합니다. 그러나 두 번째의 첫 번째에만 \n 일치합니다. 즉 결과는 다음과 같습니다 :

"One\r\n\nTwo\r\nThree" 

동일한 결과를 가진 몇 가지 다른 regexp 엔진에서 이것을 시도했습니다.

결국 나는 정규식에 내장 된 대신에 Oniguruma을 사용하여 이것을 해결할 수 있었지만, 예상했던대로 대체 접근법이 왜 작동하지 않는지에 관심이 있습니다.

답변 해 주셔서 감사합니다.

답변

1

원래 정규식이 작동하지 않는 이유를 설명하기 위해 (rsp의 의견은 똑같이 말합니다). 정규식 엔진이 먼저 ^ 문자에 ([^\r])\n 일치합니다

One\r\n\nTwo\r\nThree 
    ^

그것은 지금 ([^\r])\n 일치하려고 있지만 문자는 없다 : 첫 번째 교체 후

One\r\n\nTwo\r\nThree 
    ^^^^ 

, 정규식 엔진은 ^에있다 캐럿 위치에 \n이 아닙니다. 따라서 \r\nTwo에서 Three 사이가 될 때까지 일치하지 않습니다.

+0

내 결론은 ([^ \ r])이어야합니다? \ n 거기에 문자가없는 경우를 다루시겠습니까? –

+0

@ Ape-inago :'([^ \ r])? \ n'은'\ n', 심지어'\ r \ n '과도 일치합니다. Bart는 이미 내가 말하는 최고의 솔루션을 게시했습니다. – Andomar

+0

그래서 첫 번째 교체 후 regexp 커서가 두 번째 \ n에있는 것을 보셨습니까? [^ \ r]과 (과) 일치하는 T와 Two가 일치하지 않는 \ n과 비교됩니다.실제로 문자 위치의 길이가 일치를 통해 대체 부분에 여분의 문자를 추가하여 변경 되었기 때문에 문제가 발생 했습니까? – mikej

1

당신은 단순히 \r\n\r?\n을 대체 할 수 :

s = s.gsub(/\r?\n/, "\r\n") 

그런 식으로 모든 \r\n 's 및 \n's은 (는) \r\n로 대체됩니다.

+0

감사합니다. Oniguruma gem에 대한 의존성을 제거하지만 여전히 다른 정규 표현식이 작동하지 않는 이유에 대해 관심이 있습니다. – mikej

+2

첫 번째 '\ n'이 '\ r \ n'으로 대체 된 후 'One \ n \ nTwo'에서 두 번째'\ n '앞에 문자가 없으므로'[^ \ r ]'를 사용하십시오. – rsp

+2

"s.gsub! (/ ([^ \ r]) (? = \ n) /,"\\ 1 \ r ")'과 같이 라인 피드를 일치시켜 원래의 접근 방식을 적용 할 수 있습니다. 그러나'\ n'가 첫 번째 문자이기 때문에 Bart의 방법이 더 정확하고 명확합니다. –

관련 문제