Grep заменяют в нескольких XML-файлах

Я имею ниже команды для нахождения весь .xml файлы, содержащие <active>true</active> наличие <codePool>community</codePool> после той строки на следующей строке.

grep -rzl '<active>true</active>.*<codePool>community</codePool>' --include='*.xml' --color=always

Теперь, как объединить это с sed заменять true представьте в виде строки в <active>... тег к false обмануть тем подобранным строкам?

1
задан 10 November 2016 в 13:52

2 ответа

Спасибо за ответ @glennjackman, я был также успешным достижением моего требования со следующим кодом, это уязвимо, упаковывают входные изменения, но это будет последовательное хранение фиксированной структуры каталогов и формата файла XML-файлов Magento в памяти:

for filename in *.xml; do
    if grep -q '<codePool>community</codePool>' "$filename"; then
        if [[ $filename != *"Mage_"* ]]; then
            sed -i.bak 's/<active>true<\/active>/<active>false<\/active>/g' "$filename"
        fi
    fi
done

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

Hope это упрощает вещи и перенаправляет всех/целых возможных людей к пользованию внутренними библиотеками вместо того, чтобы установить сторонние инструменты, которым не позволяют установить в сетях Remote SSH/VPN.

0
ответ дан 7 December 2019 в 13:40

Необходимо использовать XML парсинг инструментов для данных XML. xmlstarlet хороший выбор. Регулярные выражения просто не достаточно мощны (каноническая ссылка)

Если Ваши данные похожи:

<root>
  <foo>
    <active>true</active>
    <codePool>private</codePool>
  </foo>
  <foo>
    <active>true</active>
    <codePool>community</codePool>
  </foo>
</root>

Затем

xmlstarlet ed --update '//active[.="true" and ../codePool="community"]' -v false file.xml

производит

<?xml version="1.0"?>
<root>
  <foo>
    <active>true</active>
    <codePool>private</codePool>
  </foo>
  <foo>
    <active>false</active>
    <codePool>community</codePool>
  </foo>
</root>

Вот awk программа, которая делает то, что Вы запрашиваете. Следует иметь в виду, что это хрупко: если вход изменится, то этот код прекратит работать. Это действительно просто использует простые строковые операции.

awk '
    BEGIN {
        marker = "<codePool>community</codePool>"
        srch = "<active>true</active>"
        repl = "<active>false</active>"
    }
    index($0, marker) {
        i = index(prev, srch)
        if (i > 0) 
            prev = substr(prev, 1, i-1) repl substr(prev, i+length(srch))
    }
    {
        if (prev) print prev
        prev = $0
    }
    END {if (prev) print prev}
'
2
ответ дан 7 December 2019 в 13:40

Другие вопросы по тегам:

Похожие вопросы: