Заменить строку только между двумя ключевыми словами - PullRequest
0 голосов
/ 10 мая 2018

У меня есть xml-файл. Я ищу в файле все href s между <autor> ... </autor> и заменил их на authref

, для этого я попытался

awk '/<autor>/,/<\/autor>/ {gsub(/href/,"authref");}{print;}'

эта команда заменяет ссылки в полном документе, а не только на ключевые слова / теги.Что я делаю не так?

пример для impout txt:

...<autor><autor_Name>name of the autor</autor_Name><autor_infos>some more text</autor_infos><Bild href_fmt="pic/autor.jpg" </Bild>
        <Fotocredit>credit infos</Fotocredit></autor>..

вывод:

...<autor><autor_Name>name of the autor</autor_Name><autor_infos>some more text</autor_infos><Bild authref_fmt="pic/autor.jpg" </Bild><Fotocredit>credit infos</Fotocredit></autor>..

Изменена часть: от "href" до "authref" , но все остальные href в остальной части документа не должны быть изменены.

Обновление: одно решение с sed:

 sed -e '/<autor>/,/<\/autor>/s/href/authref/'

Ответы [ 3 ]

0 голосов
/ 11 мая 2018

Awk заменяет sed возможно двойную семантику "адреса" на семантику single"pattern". Вот sed , эквивалентный тому, что вы делаете:

sed '/<autor>/,/<\/autor>/ s/href/authref/g'

Вот версия awk :

awk -v on=0 '
    /<autor>/   { on = 1 }
    on { gsub(/href/, "authref") }
    /<\/autor>/ { on = 0 }
    1'

Обратите внимание, что оба из них должны считаться быстрыми взломами ... ни решения sed , ни awk не гарантированно отлично работают с HTML / XML. Для такой работы лучше использовать инструмент, который правильно поддерживает синтаксический анализ XML. Еще один способ сделать это - использовать конвейер предварительной обработки / постобработки xml2 | script | 2xml, чтобы обеспечить хороший формат плоских файлов для работы линейных процессоров.

0 голосов
/ 11 мая 2018

/<autor>/,/<\/autor>/ не означает от слова <autor> до слова </autor>, вместо этого оно означает от строку, содержащую слово <autor> до строку, содержащую слово </autor>.Все ваши входные данные находятся в одной строке, поэтому ваша замена происходит во всем входном сигнале.

Никогда не используйте выражения диапазона в любом случае, поскольку они делают тривиальные задачи намного более короткими, но затем требуют полного переписывания или дублирования условий для чего-либо большего.Интересно.

В этом случае с GNU awk для мультисимвольных RS и RT это будет что-то вроде (не проверено, так как приведенный пример не подходит для полного тестирования):

awk -v RS='</?autor>' '!(NR%2){gsub(/href/,"authref")} {ORS=RT} 1' file

Это предполагает, что всегда есть совпадающие пары <autor>...</autor>, и они не могут быть вложенными (<autor>...<autor>...</autor>...</autor>) и что они не появляются в контекстах, отличных от желаемых тегов XML (например, они не появляются в строках или комментариях).

0 голосов
/ 10 мая 2018

Проблема с awk и sed в том, что они ориентированы на строки , поэтому они будут соответствовать строкам , содержащим <autor>, и заменят "href" везде в строке, не ограничиваясь только тегом автора.

Ваш тег Bild не имеет закрывающей скобки. Использование парсера XML указало бы вам на это.

$ xmlstarlet val file.xml
file.xml - invalid

После исправления:

$ xmlstarlet val file.xml
file.xml - valid
$ xmlstarlet edit --rename '//autor/Bild/@href_fmt' --value authref_fmt file.xml
<?xml version="1.0"?>
<root>
  <autor>
    <autor_Name>name of the autor</autor_Name>
    <autor_infos>some more text</autor_infos>
    <Bild authref_fmt="pic/autor.jpg"/>
    <Fotocredit>credit infos</Fotocredit>
  </autor>
</root>

Чтобы сохранить формат ввода, используйте xmlstarlet edit -O -P ...
Чтобы записать вывод обратно в файл, используйте xmlstarlet edit -L ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...