Як замінити багаторядковий код на sed?


9

У мене великий файл, в якому є спеціальні символи. Там є багаторядковий код, який я хочу замінити sed.

Це:

  text = "\
    ------                                                           ------\n\n\
    This message was automatically generated by email software\n\
    The delivery of your message has not been affected.\n\n\
    ------                                                           ------\n\n"

Потрібно перетворитись на це:

text = ""

Я спробував наступний код, але не пощастило:

sed -i '/  text = "*/ {N; s/  text = .*affected.\./  text = ""/g}' /etc/exim.conf

Він нічого не замінює і не відображає жодних повідомлень про помилки

Я грався з цим, але все, що я намагаюся, не працює.


Чи потрібно це sedчи ви відкриті до інших інструментів? Чи може бути "всередині text=блоку? Чи можуть бути text = у вашому файлі інші випадки ? Чи завжди буде 4 рядки тексту чи може бути більше / менше?
terdon

Переважно sed, або все, що не потребує установки на сервер CentOS. Інструменти з коробки
blade19899

@terdon У text = папці немає інших осіб , вихід повинен бути text = "". У файлах 891 рядок коду. Так, їй потрібно поважати інший текст.
blade19899

Ви хочете перезаписати файл або просто змінити вихід?
joH1

@Moonstroke НЕ ПЕРЕГЛЯД. Це просто потрібно замінити текст - як видно з мого запитання - на text = "". Як видно з мого запитання.
blade19899

Відповіді:


15

Перл на допомогу:

perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
  • -i~ редагує файл "на місці", залишаючи резервну копію
  • -0777 читає одразу весь файл, а не рядок за рядком

Заміна s///працює аналогічно, як у sed (тобто вона збігається, text = "за якою слідує все, окрім подвійних лапок, багато разів, аж до подвійної лапки), але в цьому випадку вона працює на весь файл.


5

Ви повинні перевірити простір шаблону і продовжувати витягувати Nрядок ext, якщо він не відповідає, наприклад

sed '/text = "/{              # if line matches text = "
:b                            # label b
$!N                           # pull in the next line (if not the last one)
/"$/!bb                       # if pattern space doesn't end with " go to label b
s/".*"/""/                    # else remove everything between the quotes
}' infile

з gnu sedви можете записати його в вигляді

sed '/text = "/{:b;$!N;/"$/!bb;s/".*"/""/}' infile

Це не дуже ефективно, краще просто вибрати діапазон /text = "/,/"/, змінити перший рядок і видалити решту:

sed '/text = "/,/"/{            # in this range
/text = "/!d                    # delete all lines not matching text = "
s/\\/"/                         # replace the backslash with quotes (this is only
}' infile                       # executed if the previous d wasn't executed)

знову ж таки, gnu sedви можете написати це як однолінійний текст:

sed '/text = "/,/"/{/text = "/!d;s/\\/"/}' infile

3

Особисто я би робив це в Perl. Якщо ми можемо припустити, що "до закриття таких немає ", ви можете зробити:

perl -0pe 's/(text\s*=\s*)".*?"/$1""/s' file

-0Сьорбає весь файл, читання його в пам'ять. В -pозначає «друк кожен рядок (тут," лінія "буде весь файл) після застосування сценарію дається -e». Сам сценарій є простим оператором підстановки. Він буде захоплювати рядок з textнаступними 0 або більше символами пробілів, ан =та 0 або більше пробілів знову ( text\s*=\s*) та зберігати його як $1. Потім він замінить захоплений візерунок, а також найкоротший цитуваний рядок, який він знайде, шаблоном ( $1) та "". sПрапор робить .матч нового рядка.


виправлення, -00читається в абзацах, а не весь файл ( ref ). Якщо текст у лапках містить порожній рядок, то регулярний вираз не збігається.
glenn jackman

@glennjackman argh! Я завжди змішую це. . Ось чому я насправді двічі перевірив, додавши додатковий абзац і запустивши perl -00ne 'print;exit'. І я все-таки поставив неправильну у своїй відповіді! Дякую, виправлено зараз.
terdon
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.