Как заменить одну строку на другую в файле (Linux)
Устал я от долгих споров, давайте что-то на техническую тему напишу. Тем более, что после двух писем с одним и тем же вопросом и одного поста внутри компании, оказалось, что такая простая вещь тянет на рецепт: как можно в bash заменить в файле одну подстроку на другую.
Вот несколько способов, которые я знаю.
Во-первых, в состав MySQL входит замечательная утилита replace, которая замечательна тем, что умеет производить замену прямо в файле:
replace 'hello' 'bye, bye!' -- myfile
Самое замечательное, что она умеет менять пары подстрок, что позволяет производить такие замены:
bolk-dev ~ $ echo ABBA | replace A B B A --
BAAB
Второй способ — создать временный файл, заменить в нём символы или подстроки какой-нибудь утилитой (sed, tr), переместить временный файл на прежнее место (не забудьте, что sed работает с регулярными выражениями):
T=`/bin/tempfile`
sed 's/hello/bye, bye!/g' myfile > $T
mv $T myfile
Сразу в тот же файл записывать результат нельзя, операция „>“ сразу же откроет файл на запись и обнулит его. Поможет утилита sponge (входит в пакет moreutils):
sed 's/hello/bye, bye!/g' myfile | sponge myfile
Она запишет stdin в файл разом, после того как все данные будут получены.
Добавлено: Азат в комментариях подсказывает, что можно воспользоваться ключом «-i» у sed:
sed -i 's/hello/bye, bye!/g' myfile
А как же perl -i.bak?
Тоже вполне себе in-place заменяет.
Комментарий для blog.vnaum.com:
Тогда почему не python/php/чтоугодноещё?
Всегда использую sed -i
Комментарий для razetdinov.ya.ru:
О! Не знал, спасибо!
Комментарий для Евгения Степанищева:
Потому что однострочники — это специализация Perl.
Ну и потому что там регекспы perl-compatible, со всеми вкусностями.
Опять же,
perl -i.bak -pne ’s/hello/bye, bye!/g’ myfile
ничем не хуже
sed -i ’s/hello/bye, bye!/g’ myfile
Комментарий для Евгения Степанищева:
А Python/PHP/что-угодно-ещё поддеживают однострочники?
Комментарий для dionys.myopenid.com:
конечно
Комментарий для blog.vnaum.com:
ничем не хуже, кроме того что короче и sed быстрее
Комментарий для indeyets.ru:
А как в Python решается вопрос отступами для однострочника?
Комментарий для dionys.myopenid.com:
В Python можно записывать несколько команд не через перевод строки, а через точку с запятой: func1(); func2()
В блочных командах следующую можно ставить сразу после двоеточия: if x: func()
Вот так и решается.
извините но sed -i ’s/hello/bye\,\ bye\!/g’
Комментарий для Николай:
Не извиню. Зачем вы это всё дважды (у вас уже есть кавычки) заэкранировали?
Здравствуйте Евгений,
А как это сделать с двумя файлами?
Тоесть есть два файла (СтарыеЛогины.txt, НовыеЛогины.txt) и надо взять старые логины из одного
файла и заменить их во втором. Доступен только bash и/или python.
Комментарий для Юзик:
Здравствуйте!
Напишите программу на баше или пайтоне.
Тут особой разницы нет на чем (так сказать устроит любой вариан), но от баша я как то быстро отказался (может был не прав :) ) и сейчас пытаюсь все сделать на пайтоне.
Я собственно и пытаюсь написать))
Но столкнулся с проблемой что не могу создать цикл, сейчас ищу как « склеить» два файла в третий.
Комментарий для Юзик:
Простите, но я не понимаю. Вы ждёте что я вам программу напишу?
Нет программу не надо, но Вы используете sed (башь), ответте на вопрос: можно ли запустить ее в цикле? у меня ни как не получается((( sed ’s/X/Y/’ X и Y постоянно изменяются. Может это в принципе не предусмотренно?
Комментарий для Юзик:
В баше есть циклы, можно что угодно запустить в цикле. sed — тоже.