2016-04-16 3 views
-1

Я хочу, чтобы заменить строку в файле с новой строки, например, являются:Заменить строку в текстовом файле с новой строки

Файл:

test 
test 
test 
testing 
test 

Источник:

def remove_line(line) 
    if line == line 
    #remove line including whitespace 
    File.open('test.txt', 'a+') { |s| s.puts('removed successfully') } 
    end 
end 

Таким образом, ожидаемый результат этого будет примерно таким:

remove_line('testing') 
test 
test 
test 
removed successfully 
test 

Теперь я провел некоторое исследование и только смог найти добавленную пустую строку, я думаю, я мог бы запустить ее и удалить все пустые строки и просто добавить к файлу, но должен быть более простой способ заменить строка с другой строкой?

+0

Когда вы говорите 'if line == line', что вы пытаетесь сделать? Это всегда будет правдой. – Nobita

+0

@Nobita Я думаю, что он ссылается на него как на пример, если строка, заданная в качестве аргумента, равна одной из строк в файле, переписывает строку и т. Д. – 13aal

ответ

1

Во-первых, откройте файл и сохранить фактический контент. Затем замените строку и напишите полный контент обратно в файл.

def remove_line(string) 
    # save the content of the file 
    file = File.read('test.txt') 
    # replace (globally) the search string with the new string 
    new_content = file.gsub(string, 'removed succesfully') 
    # open the file again and write the new content to it 
    File.open('test.txt', 'w') { |line| line.puts new_content } 
end 

Или, вместо того, чтобы заменить глобально:

def remove_line(string) 
    file = File.read('test.txt') 
    new_content = file.split("\n") 
    new_content = new_content.map { |word| word == string ? 'removed succesfully' : word }.join("\n") 
    File.open('test.txt', 'w') { |line| line.puts new_content } 
end 
+0

Это перезаписывает всю file – JasonBorne

+0

Он записывает в файл именно то, что вам нужно. Вы можете попробовать использовать «File.seek», который не будет переписывать весь файл, но вам нужно будет заменить строку другой строкой с точно таким же размером. – user3097405

+0

отредактировал второй метод, потому что я оставил оператор, чтобы заменить строку глобально. – user3097405

0

Я нашел справочный ответ here Это не совсем то же самое, потому что они ищут шаблон.

Так вот как я бы идти об этом:

def remove_line(line) 
    file.open('test.txt', 'a+').each_line do |line| 
    line.gsub('<line/to/replace>', '<new/line/here>') 
    end 
end 

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

+0

Это не работает. – JasonBorne

0

Учитывая этот входной файл, хранится в виде "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 

Теперь у вас есть власть делать интересные вещи, созданные из других интересных вещей. Используйте его мудро и продолжайте делать это Рубиновый путь.

Смежные вопросы