Нормализация концов строк в Ruby

У меня есть строка в Ruby, s (скажем), которая может иметь любое из стандартных окончаний строки (\n, \r\n, \r). Я хочу преобразовать все это в \ns. Какой лучший способ?

Это кажется очень распространенной проблемой, но документации по ней не так много. Очевидно, что есть простые грубые решения, но есть ли что-нибудь встроенное, чтобы справиться с этим?

Лучше всего элегантные, идиоматические решения на Ruby.

РЕДАКТИРОВАТЬ: понял, что ^M и \r одинаковы. Но есть еще три случая. (См. википедию.)


person Peter    schedule 02.12.2009    source источник


Ответы (4)


Лучше всего просто обработать два случая, которые вы хотите изменить конкретно, и не пытаться слишком умничать:

s.gsub /\r\n?/, "\n"
person Josh Lee    schedule 02.12.2009
comment
Две вещи: вы должны поставить \r\n первым в регулярном выражении, иначе оно никогда не будет соответствовать (потому что все, что в противном случае могло бы соответствовать b \r\n, будет сначала сопоставлено с \r). И '\n' == \\n, а вам нужно \n. - person sepp2k; 03.12.2009
comment
Измените одинарные кавычки на двойные кавычки. В противном случае это не работает, как задумано. - person Mikael S; 03.12.2009
comment
Кажется, мы все на одной волне :) - person Josh Lee; 03.12.2009
comment
хорошо сделано, что вы не утруждаете себя изменением регистра по умолчанию (\n -> \n не нужен. Сначала не совсем понял это :) - person Peter; 03.12.2009
comment
Интересный ответ; Интересно, почему в Ruby нет чего-то вроде os.linesep в python? - person ; 12.08.2012
comment
было бы здорово получить ответ, в котором использовалась бы эта строка кода. Все детали, связанные с файлом, строкой чтения и т. д. Контекст, в который вписывается эта строка. - person ahnbizcad; 01.09.2016

Начиная с ruby ​​1.9 вы можете использовать String::encode с universal_newline: true чтобы получить все ваши новые строки в \n, сохраняя при этом кодировку неизменной:

s.encode(s.encoding, universal_newline: true)

Оказавшись в известном состоянии новой строки, вы можете свободно конвертировать обратно в CRLF, используя :crlf_newline. например: чтобы преобразовать файл с неизвестным (возможно, смешанным) окончанием в CRLF (например), прочитайте его в двоичном режиме, затем:

s.encode(s.encoding, universal_newline: true).encode(s.encoding, crlf_newline: true)
person Greg    schedule 08.01.2014
comment
Вам не нужно включать первый s.encoding, достаточно простых s.encode(universal_newline: true) или s.encode(crlf_newline: true). Это помогло мне с проектом сегодня. - person Donovan; 03.12.2014
comment
@Donovan - Вы вероятно правы, однако в документации говорится, что версия без явного кодирования будет перекодирована в Encoding.default_internal, что может быть, а может и не быть тем, что вам нужно. Моя версия консервативно сохранит вашу текущую кодировку. - person Greg; 05.12.2014
comment
true, и вы делаете хорошее замечание, но в большинстве случаев по умолчанию все в порядке, в конце концов, это то, что использует String.new. Так что в моем случае (а я могу утверждать, что в большинстве случаев) это было бы лишним. - person Donovan; 06.12.2014
comment
Это, по-видимому, намного быстрее, чем другие методы (занимает на 40% меньше времени, чем метод gsub, тогда как раздельное соединение занимает примерно на 40% больше времени). Я сравнил это с: s.gsub(/\r\n?/, "\n"), s.gsub("\r\n", "\n").gsub("\r", "\n") (примерно такая же скорость) и s.split(/\r\n?/).join("\n") - person Kanat Bolazar; 22.01.2016

Я думаю, что самым чистым решением было бы использование регулярного выражения:

s.gsub! /\r\n?/, "\n"
person Mikael S    schedule 02.12.2009
comment
упс, здесь есть ловушка: двойные разрывы строк, такие как \n\n, станут \n. - person Peter; 03.12.2009
comment
Ой, спасибо, что указали на это, кажется, jleedev был немного быстрее. - person Mikael S; 03.12.2009

Попробуйте открыть их в среде IDE NetBeans. Раньше меня спрашивали в одном из проектов, которые я открывал из других источников, хочу ли я исправить окончания строк. Я думаю, что может быть опция меню, чтобы сделать это, но это было бы первое, что я бы попробовал.

person Ash    schedule 02.12.2009
comment
спасибо, но это не единичный случай; это для обработки данных в Ruby, а не для обработки файлов Ruby. - person Peter; 03.12.2009