Ruby File не читает содержимое после последней пустой строки \n

Я пытаюсь написать очень простой ruby-скрипт, который открывает текстовый файл, удаляет \n из конца строк, ЕСЛИ строка не начинается с небуквенного символа ИЛИ сама строка пуста (\n).

Приведенный ниже код работает нормально, за исключением того, что он пропускает все содержимое после последней строки \n. Когда я добавляю \n\n в конец файла, он работает отлично. Примеры: файл с этим текстом отлично работает и стягивает все в одну строку:

Hello
there my
friend how are you?

становится Hello there my friend how are you?

Но текст такой:

Hello

there

my friend
how
are you today

возвращает только Hello и There и полностью пропускает последние 3 строки. Если я добавлю 2 пустые строки в конец, он подхватит все и будет вести себя так, как я хочу.

Может ли кто-нибудь объяснить мне, почему это происходит? Очевидно, я знаю, что могу исправить этот экземпляр, добавив \n\n в конец исходного файла в начале, но это не помогает мне понять, почему .gets не работает так, как я ожидал.

Заранее благодарю за любую помощь!

source_file_name = "somefile.txt"
destination_file_name = "some_other_file.txt"
source_file = File.new(source_file_name, "r")

para = []
x = ""
while (line = source_file.gets)
  if line != "\n"
    if line[0].match(/[A-z]/)   #If the first character is a letter
        x += line.chomp + " "
    else
      x += "\n" + line.chomp + " "
    end
  else
    para[para.length] = x
    x = ""
  end
end

source_file.close

fixed_file = File.open(destination_file_name, "w")
para.each do |paragraph|
  fixed_file << "#{paragraph}\n\n"
end
fixed_file.close

person ShawnyV    schedule 24.05.2012    source источник
comment
Пустая строка не является \n. Также /[A-z]/ может не делать того, что вы думаете.   -  person pguardiario    schedule 24.05.2012


Ответы (3)


Ваша проблема заключается в том, что вы добавляете свою строку x в массив para только тогда и только тогда, когда встречаете пустую строку ('\n'). Поскольку ваш второй пример не содержит пустой строки в конце, окончательное содержимое x никогда не добавляется в массив para.

Самый простой способ исправить это без изменения кода — добавить следующие строки после закрытия цикла while:

if(x != "")
    para.push(x)
end

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

Также,

para.push(x)
para << x

оба читаются намного приятнее и выглядят более прямолинейными, чем

para[para.length] = x

Это сбило меня с толку на секунду, так как в нединамических языках это дало бы вам ошибку. Вместо этого я советую использовать один из них просто потому, что он более удобочитаем.

person domvoyt    schedule 24.05.2012

Ваш код для меня как код c, ruby way должен быть таким, который заменяет ваши выше 100 строк.

File.write "dest.txt", File.read("src.txt")
person c2h2    schedule 24.05.2012

Проще использовать многострочное регулярное выражение. Может быть:

source_file.read.gsub(/(?<!\n)\n([a-z])/im, ' \\1')
person pguardiario    schedule 24.05.2012