Команда Linux для замены строки в БОЛЬШОМ файле другой строкой

У меня есть огромный файл SQL, который выполняется на сервере. Дамп с моей машины, и в нем есть несколько настроек, относящихся к моей машине. В общем, я хочу, чтобы каждое вхождение "c://temp" было заменено на "//home//some//blah"

Как это можно сделать из командной строки?


person coderama    schedule 07.08.2009    source источник
comment
В вашей команде отсутствует завершающий % . Это s%foo%bar%, а не s%foo%bar   -  person Vinko Vrsalovic    schedule 07.08.2009


Ответы (7)


sed — хороший выбор для больших файлов.

sed -i.bak -e 's%C://temp%//home//some//blah%' large_file.sql

Это хороший выбор, потому что не нужно читать весь файл сразу, чтобы изменить его. Цитирую мануал:

Редактор потока используется для выполнения основных преобразований текста во входном потоке (файле или вводе из конвейера). Хотя в некотором смысле он похож на редактор, допускающий редактирование по сценарию (например, ed), sed работает, выполняя только один проход по входным данным, и, следовательно, более эффективен. Но способность sed фильтровать текст в конвейере особенно отличает его от других типов редакторов.

Соответствующий раздел руководства находится здесь. Далее следует небольшое пояснение

-i.bak позволяет редактировать на месте, оставляя резервную копию с расширением .bak

s%foo%bar% использует s, команду подстановки, которая заменяет совпадения первой строки между знаком %, 'foo', на вторую строку, 'bar'. Обычно это записывается как s//, но поскольку в ваших строках много косых черт, удобнее заменить их на что-то другое, чтобы вам не приходилось их экранировать.

Пример

vinko@mithril:~$ sed -i.bak -e 's%C://temp%//home//some//blah%' a.txt
vinko@mithril:~$ more a.txt
//home//some//blah
D://temp
//home//some//blah
D://temp
vinko@mithril:~$ more a.txt.bak
C://temp
D://temp
C://temp
D://temp
person Vinko Vrsalovic    schedule 07.08.2009
comment
Вы можете использовать другой символ, чтобы не заключать косую черту в кавычки, например, sed -e s%C://temp%/home//some//blah%. Кроме того, параметр -i позволяет сохранить файл на месте, если вы уверены в параметрах. - person dalloliogm; 07.08.2009
comment
Это команда, которую я набираю: sed -i.bak -e 's%C:\\temp\%/home/liveon/public_html/tmp' liveon.sql, и это ошибка, которую я получаю: sed: -e выражение #1, char 41: неопределенная команда `s' Кто-нибудь? - person coderama; 07.08.2009
comment
Кроме того, RD, убедитесь, что вы правильно экранируете обратную косую черту. - person Dave Jarvis; 07.08.2009

Просто для полноты. Вместо замены с использованием perl.

perl -i -p -e 's{c://temp}{//home//some//blah}g' mysql.dmp

Также не требуется экранирование обратной косой черты. ;)

person ire_and_curses    schedule 07.08.2009
comment
Обратите внимание, что если вы используете флаг -i без расширения, вы не получаете не резервную копию. Если вам нужна резервная копия, попробуйте -i.bak, которая выполнит редактирование на месте и предоставит вам резервную копию оригинала как original.bak практически бесплатно. - person Telemachus; 07.08.2009
comment
Я позволяю своей системе контроля версий делать резервные копии. - person jrockway; 08.08.2009
comment
@Jrockway: это прекрасно для вас, я уверен, но предполагается, что рассматриваемые файлы находятся под контролем версий и что вы знаете, что делает -i.bak, и решили не использовать его. Я просто хочу, чтобы люди, которые рекомендуют переключатель -i, потратили две секунды, чтобы объяснить разницу между -i и -i.bak. Будет действительно больно, если файлы, с которыми вы играете, не находятся под контролем версий, и вы сделаете простую опечатку (например, забудете флаг -p). - person Telemachus; 08.08.2009

Попробуйте sed? Что-то типа:

sed 's/c:\/\/temp/\/\/home\/\/some\/\/blah/' mydump.sql > fixeddump.sql

Однако экранирование всех этих слэшей выглядит ужасно, вот более простой пример, который заменяет foo на bar.

sed 's/foo/bar/' mydump.sql > fixeddump.sql

Как уже отмечали другие, вы можете выбрать свой собственный разделитель, который предотвратит синдром наклонной зубочистки в Это дело:

sed 's|c://temp\\|home//some//blah|' mydump.sql > fixeddump.sql

Преимущество sed в том, что он работает с потоком, а не со всем файлом одновременно, поэтому вы можете обрабатывать огромные файлы, используя лишь скромный объем памяти.

person Paul Dixon    schedule 07.08.2009
comment
Спасибо, Пол! Intellij Idea сходит с ума и делает это в течение десятков минут, тогда как с sed требуется всего 1 секунда, чтобы заменить обратную косую черту на двойную обратную косую черту в моем файле sql. - person humkins; 21.10.2013

Существует также нестандартная утилита UNIX, rpl, которая делает то же самое, что и sed примеры делают; однако я не уверен, работает ли rpl в потоке, поэтому sed здесь может быть лучшим вариантом.

person Meredith L. Patterson    schedule 07.08.2009
comment
Хех, случайно не друг разработчика rpl? :-) - person Vinko Vrsalovic; 07.08.2009
comment
Нет, никогда не слышал об этом парне за пределами утилиты; однажды он пригодился для выполнения пакетной замены нескольких тысяч текстовых файлов, и я сохранил его в своем наборе инструментов. - person Meredith L. Patterson; 07.08.2009
comment
Стоит сказать, почему вы рекомендуете это в данном случае (или почему вы могли бы, поскольку вы наполовину отказываетесь от рекомендации). То есть, вместо того, чтобы просто кидать название утилиты, расскажите, что вам в ней понравилось, пожалуйста. - person Telemachus; 07.08.2009
comment
rpl хорош для простых замен, потому что он имеет гораздо более удобный синтаксис, чем комбинация sed и find, которую он заменяет. Он также имеет удобную функцию пробного запуска, где он скажет вам, что он заменит, фактически не выполняя замену. Его основное ограничение заключается в том, что он выполняет только прямые замены и не использует регулярные выражения. - person Tyler McHenry; 07.08.2009
comment
@Telemachus - Тайлер попал в точку. - person Meredith L. Patterson; 07.08.2009

Команда sed может это сделать. Вместо экранирования косой черты вы можете выбрать другой разделитель (в данном случае _):

sed -e 's_c://temp/_/home//some//blah/_' file1.txt > file2.txt
person stefanw    schedule 07.08.2009
comment
вы пропустили последнее подчеркивание: s_c://temp/_/home//some//blah_ - person dalloliogm; 07.08.2009

perl -pi -e 's#c://temp#//home//some//blah#g' yourfilename

-p будет рассматривать этот скрипт как цикл, он будет читать указанный файл построчно, выполняя поиск и замену регулярных выражений.

-i Этот флаг следует использовать вместе с флагом -p. Это дает Perl команду отредактировать файл на месте.

-e Просто означает выполнить этот код perl.

Удачи

person Logan    schedule 07.08.2009

пялиться

awk '{gsub("c://temp","//home//some//blah")}1' file
person ghostdog74    schedule 07.08.2009