Учитывая этот входной файл, хранится в виде "test.txt":
test
test
test
testing
test
и этот пример кода:
def remove_line(line_to_remove)
File.foreach("test.txt").with_index do |line, line_num|
line.gsub!(/[\r\n]+$/, '')
if line == line_to_remove
puts "removed successfully"
else
puts line
end
end
end
Вы можете успешно запустить:
remove_line('testing')
и получить этот результат:
test
test
test
removed successfully
test
Функция принимает содержимое строки для удаления, и открывает файл в моде «строка за строкой». Это идиоматический Ruby, и он должен быть предпочтительнее, чем «разрывать» файлы, как объясняется в принятом ответе на этот вопрос SO question.
Как только у нас есть линия, необходимо снять с нее линии. Поскольку мы точно не знаем, на какой платформе это будет выполняться (или был создан текстовый файл), мы используем регулярное выражение для поиска всех известных символов окончания строки ('\ r \ n' - это Windows, '\ n' это Linux/Unix/Mac OS X, а «\ r» - Mac Classic).
Затем мы проверяем, соответствует ли линия тем, что мы хотим удалить. Если он соответствует, мы опускаем его из вывода и вместо этого печатаем, что он был «удален успешно»; в противном случае мы выводим несогласованную строку.
Это соответствует первоначальному намерению проекта, однако есть много вещей, которые нужно сделать, чтобы улучшить дизайн и сделать общую более полезную функцию. Так почему бы не пойти дальше и сделать это?
Во-первых, мы сделаем функцию для имени файла в качестве аргумента. Это приведет к удалению жесткокодированного имени файла "test.txt"
из вызова foreach
. Это сделает это изменение произошло:
def remove_line(filename, line_to_remove)
File.foreach(filename).with_index do |line, line_num|
line.gsub!(/[\r\n]+$/, '')
if line == line_to_remove
puts "removed successfully"
else
puts line
end
end
end
Вы можете успешно запустить его таким образом, и он будет производить тот же вывод:
remove_line("test.txt", "testing")
Далее, давайте изменим, как происходит выход, и мы Я использую блок для этого, потому что это The Ruby Way. Вот то, что функция выглядит с блоком для вывода:
def remove_line(filename, line_to_remove, &block)
proc = block_given? ? block : lambda {|s| puts s }
File.foreach(filename).with_index do |line, line_num|
line.gsub!(/[\r\n]+$/, '')
if line == line_to_remove
proc.call "removed successfully"
else
proc.call line
end
end
end
Это построен с дополнительным блоком аргумента, так что вы можете назвать это так же, как в предыдущей версии, чтобы заставить его работать точно так же, или вы можете назовите его явным блоком и сделайте что-нибудь классное. Этот пример запуска он изменяет строку немного перед вызовом puts
напечатать строку:
remove_line("test.txt", "testing") {|s| puts "#{s} in your pants" }
И с этой дополнительной щепоткой детскости, вы получите этот результат:
test in your pants
test in your pants
test in your pants
removed successfully in your pants
test in your pants
Теперь у вас есть власть делать интересные вещи, созданные из других интересных вещей. Используйте его мудро и продолжайте делать это Рубиновый путь.
Когда вы говорите 'if line == line', что вы пытаетесь сделать? Это всегда будет правдой. – Nobita
@Nobita Я думаю, что он ссылается на него как на пример, если строка, заданная в качестве аргумента, равна одной из строк в файле, переписывает строку и т. Д. – 13aal