Почему это регулярное выражение не соответствует смежным вхождениям новой строки? - PullRequest
0 голосов
/ 13 ноября 2009

Я пытался написать регулярное выражение для замены всех вхождений \n на \r\n, если только \n сразу не предшествует \r. Я делаю это в Ruby 1.8.6, который не поддерживает просмотр в регулярных выражениях, поэтому я попытался:

# 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

С учетом строки One\n\nTwo\r\nThree предполагалось заменить \n\n на \r\n\r\n, а существующие \r\n между Two и Three оставить без изменений. Однако только первый из двух \n совпадает. то есть результат:

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

Я пробовал это на нескольких других движках регулярных выражений с тем же результатом.

В конце концов я смог решить эту проблему, используя Онигурума (который поддерживает положительный и отрицательный взгляд позади) вместо встроенных в Ruby регулярных выражений, но меня все еще интересует, почему мой альтернативный подход не сделал работать как я ожидал.

Спасибо за любые ответы.

Ответы [ 2 ]

1 голос
/ 13 ноября 2009

Просто пишу, чтобы объяснить (комментарий rsp говорит то же самое), почему ваше оригинальное регулярное выражение не сработало. Движок регулярных выражений сначала соответствует ([^\r])\n с ^ символами:

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

После первой замены двигатель регулярного выражения находится на ^:

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

Теперь он пытается сопоставить ([^\r])\n, но в позиции каретки нет символа, который не \n. Так что он не будет совпадать, пока \r\n между Two и Three.

1 голос
/ 13 ноября 2009

Вы можете просто заменить \r?\n на \r\n:

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

Таким образом, все \r\n и \n заменяются на \r\n.

...