Это сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

Как заменить одну строку на другую в файле (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
19 комментариев
vnaum (blog.vnaum.com) 2010

А как же perl -i.bak?
Тоже вполне себе in-place заменяет.

Евгений Степанищев (bolknote.ru) 2010

Комментарий для blog.vnaum.com:

Тогда почему не python/php/чтоугодноещё?

Азат Разетдинов (razetdinov.ya.ru) 2010

Всегда использую sed -i

Евгений Степанищев (bolknote.ru) 2010

Комментарий для razetdinov.ya.ru:

О! Не знал, спасибо!

blog.vnaum.com 2010

Комментарий для Евгения Степанищева:

Потому что однострочники — это специализация Perl.
Ну и потому что там регекспы perl-compatible, со всеми вкусностями.

Опять же,
perl -i.bak -pne ’s/hello/bye, bye!/g’ myfile
ничем не хуже
sed -i ’s/hello/bye, bye!/g’ myfile

Denis Ibaev (dionys.myopenid.com) 2010

Комментарий для Евгения Степанищева:

А Python/PHP/что-угодно-ещё поддеживают однострочники?

jimidini (indeyets.ru) 2010

Комментарий для dionys.myopenid.com:

конечно

Евгений Степанищев (bolknote.ru) 2010

Комментарий для blog.vnaum.com:

ничем не хуже, кроме того что короче и sed быстрее

Denis Ibaev (dionys.myopenid.com) 2010

Комментарий для indeyets.ru:

А как в Python решается вопрос отступами для однострочника?

Евгений Степанищев (bolknote.ru) 2010

Комментарий для dionys.myopenid.com:

В Python можно записывать несколько команд не через перевод строки, а через точку с запятой: func1(); func2()

В блочных командах следующую можно ставить сразу после двоеточия: if x: func()

Вот так и решается.

Николай 2015

извините но sed -i ’s/hello/bye\,\ bye\!/g’

Евгений Степанищев (bolknote.ru) 2015

Комментарий для Николай:

Не извиню. Зачем вы это всё дважды (у вас уже есть кавычки) заэкранировали?

Юзик 2016

Здравствуйте Евгений,

А как это сделать с двумя файлами?
Тоесть есть два файла (СтарыеЛогины.txt, НовыеЛогины.txt) и надо взять старые логины из одного
файла и заменить их во втором. Доступен только bash и/или  python.

Евгений Степанищев (bolknote.ru) 2016

Комментарий для Юзик:

Здравствуйте!

Напишите программу на баше или пайтоне.

Юзик 2016

Тут особой разницы нет на чем (так сказать устроит любой вариан), но от баша я как то быстро отказался (может был не прав :) ) и сейчас пытаюсь все сделать на пайтоне.

Юзик 2016

Я собственно и пытаюсь написать))
Но столкнулся с проблемой что не могу создать цикл, сейчас ищу как « склеить» два файла в третий.

Евгений Степанищев (bolknote.ru) 2016

Комментарий для Юзик:

Простите, но я не понимаю. Вы ждёте что я вам программу напишу?

Юзик 2016

Нет программу не надо, но Вы используете sed (башь), ответте на вопрос: можно ли запустить ее в цикле? у меня ни как не получается((( sed ’s/X/Y/’ X и Y постоянно изменяются. Может это в принципе не предусмотренно?

Евгений Степанищев (bolknote.ru) 2016

Комментарий для Юзик:

В баше есть циклы, можно что угодно запустить в цикле. sed — тоже.