Удалить символ между двумя известными строками

У меня есть набор данных, как показано ниже:

\"XXX \ START sapiodj \\" aj \d 2387 END hddo\" START bbcc \\" END ss 

Мои требования: я хочу удалить все вхождения обратной косой черты и двойные кавычки между START и END.

Желаемый результат:

 \"XXX \ START sapiodj aj d 2387 END hddo\" START bbcc END ss 

Заметка:

  1. Несколько START / END в одной строке
  2. Я хочу удалить \ и " только между START и END и нигде больше
  3. И мой файл имеет несколько строк (строки, похожие на то, что показано выше)
  4. Мне нужно использовать только sed

Я попробовал что-то вроде ниже (сначала пытался избавиться от " одного»), и это не дало мне желаемого результата:

 sed '/START/,/END/ s/"//g' 

  • странное поведение при сопоставлении шаблонов sed
  • Как отредактировать второе появление дубликатов строк?
  • Редактирование AIX - на месте
  • Почему это совмещение регулярных выражений?
  • Как правильно использовать кавычки в sed?
  • Вставить новые строки с sed?
  • Работает ли ] для sed шаблонов на всех дистрибутивах Linux?
  • Как использовать sed, awk или grep для удаления определенного шаблона, но все остальное
  • 4 Solutions collect form web for “Удалить символ между двумя известными строками”

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

     sed -e 's/END/`/g;:X' -e 's/\(START[^`]*\)["\]/\1/g;tX' -e 's/`/END/g' 

    На самом деле это не так сложно. Вы всегда можете разграничить раздел с помощью \n ewline или вы можете разложить разделитель на \n ewline временно. И вы можете сделать это без цикла:

     sed 's/$/START/;s/END/& /g; y/D\n/\nD/ s/\([^D]*START\)*[D\"]*/\1/g y/\n/D/;s/.....$// ' <<\IN \"XXX \ START sapiodj \\" aj \d 2387 END hddo\" START bbcc \\" END ss IN 

    Иногда вам просто нужно немного подумать о проблеме. Вместо того, чтобы удалить все « \\" между START и END если мы вместо этого перейдем к проблеме, как мы можем сохранить \\" только если они происходят между главой строки и START , START и END , а последний END и хвост линии становится немного легче (если, по общему признанию, не интуитивно так) . Это связано с тем, как sed обрабатывает * совпадения s/// нулем или больше в контексте g lobal s/// ubstitution .

    В то время как бит START -1- START будет вымываться как естественный результат остальной части этого, последний бит END -to-tail не будет – и поэтому нам нужно добавить еще один START в конец строки , После получения нашего дополнительного START мы добавим символ \n ewline к каждому появлению END . И затем с помощью команды y/// транслитерации мы одновременно продаем все D символы для \n ewlines и наоборот. Кстати, команда y/// транслитерации не только очень удобна здесь, но и более эффективна, чем s/// ubstitution.

    На этом этапе в нашем пространстве шаблонов будет напечатан:

     \\"XXX \\ START sapiodj \\\\" aj \\d 2387 EN\nD hddo\\" START bbcc \\\\" EN\nD ssSTART$ 

    Как вы можете видеть, теперь все \\" символы, требующие сохранения, лежат прямо между головой строки или строками D и START и между ними нет D s. Таким образом, g lobal s/// ubstitution, который удаляет нежелательные символы – для включения наших дополнительных D s – также заменяют те, которые требуют экономии с собой. Последнее нам нужно только для замены \n и D s и удаления последнего START .

    Таким образом, вы можете надежно делиться полями с sed независимо от ввода, и вам не нужно полагаться на любого несуществующего персонажа, но тот, который гарантированно никогда не будет происходить на линии, – и это, конечно, символ \n .

    Когда он закончит печать, выполните следующие действия:

     \"XXX \ START sapiodj aj d 2387 END hddo\" START bbcc END ss 

    С sed :

     sed 's/:/::/g;s/</:l/g;s/>/:g/g; # escape :, <, > s/START/&</g; s/END/>&/g; # replace START/END with <> :1 s/\(<[^>]*\)[\"]/\1/g;t1 s/[<>]//g;s/:g/>/g;s/:l/</g;s/::/:/g; # restore <>:' 

    С perl :

     perl -pe's|START.*?END|$&=~y/\\"//rd|ge' 

    Вы указали в комментарии, что awk также разрешен. Поэтому я основываю свой ответ на этом.

    Предполагая, что ваши START и END сбалансированы, если вы разделите строку на любом слове, вы обнаружите, что хотите удалить обратную косую черту и двойные кавычки из всех четных полей. К этому концу:

     awk -F 'START|END' '{ for(i=2;i<=NF;i+=2){ # For each even-numbered field gsub(/["\\]/,"",$i) # Remove " and \ from it $i="START"$i"END" # Put START and END back around it } }' your_file 

    Это предполагает, что ваша реализация awk имеет функцию gsub которую я не могу ручаться.

    В качестве побочного примечания ваш sed не работает, потому что он в основном говорит «применить подстановку к диапазону строк, который начинается с строки, соответствующей START и заканчивается линией, соответствующей END ».

    Interesting Posts

    Fedora 23 больше не загружается (GRUB: поддерживается минимальное редактирование строк в формате BASH).

    su пользователь терпит неудачу с «grep: / var / cpanel / users / user: Permission denied»

    Как настроить драйвер для eth0, чтобы я мог использовать файл кикстарта по сети?

    труба в качестве аргументов

    Есть ли способ загрузить файл 32-разрядного файла Google Chrome для Ubuntu?

    Проблема с Debian Squeeze и Wheezy mixed

    файлы в / proc / $ PID (например, ssh-agent, Chrome) не принадлежат пользователю, а root

    Как запустить сложный awk-скрипт на удаленной машине?

    Почему я не слышу звук, воспроизводимый в моем блендере CentOS 6.5 Vagrant?

    Список всех уникальных строк в определенном столбце

    Невозможно установить клиентские библиотеки MySQL на Gentoo

    Не удалось разрешить имя хоста

    Что означает последний выходной параметр команды lsusb -t?

    Поиск файлов и содержимого эха в оболочке

    Задачи автоматизации для системных администраторов

    Linux и Unix - лучшая ОС в мире.