Крошечная проблема: ваше регулярное выражение не делает то, что вы думаете./[^"label2: "]*\z/
означает: любое количество символов в конце строки, которые не a
, b
, e
, l
, "
, пробел, двоеточие или 2
(см. Символклассы ).И scan
возвращает массив, с которым sub
не работает.Но это не имеет значения, потому что ...
Небольшая проблема: line.sub(foo_string, bar)
ничего не делает.Он возвращает измененную строку, но вы ничего не назначаете, и она выбрасывается.line.sub!(foo_string, bar)
изменит сам line
, но это приводит нас к ...
Большая проблема: вы не можете просто изменить строку чтения и ожидать, что она изменится в самом файле.Это все равно что читать книгу, думать, что можно написать строчку лучше, и ожидать, что она изменит книгу.Чтобы изменить строку в текстовом файле, нужно прочитать один файл и скопировать прочитанное в другой .Если вы измените грань между чтением и записью, вновь написанная копия будет отличаться.В конце вы можете переименовать новый файл в старый (что приведет к удалению старого файла и его атомной замене новым).
РЕДАКТИРОВАТЬ: Вот некоторый код.Во-первых, мне не нравится IO.foreach
, так как мне нравится самому управлять итерацией (и IMO, IO.foreach
не читается как IO#each_line
).В регулярном выражении я использовал lookbehind, чтобы найти метку, не включая ее в совпадение, поэтому я могу заменить только значение;Я изменил на \Z
по той же причине, чтобы исключить перевод строки из матча.Вы не должны возвращать сообщения об ошибках из функций, для этого есть исключения.Я изменил простой include?
на #start_with?
, потому что ваш item
может быть найден в другом месте строки, когда мы не хотим запускать изменение.
class FileNotFoundException < RuntimeError; end
def replace_info(item, bar)
# check if file exists
raise FileNotFoundException unless File.exist?('site_info.txt')
# rewrite the file
File.open('site_info.txt.bak', 'wt') do |w|
File.open('site_info.txt', 'rt') do |r|
r.each_line do |line|
if line.start_with?("[#{item}]")
line.sub!(/(?<=label2: ).*?\Z/, bar)
end
w.write(line)
end
end
end
# replace the old file
File.rename('site_info.txt.bak', 'site_info.txt')
end
replace_info("item", "bar")