2016-09-26 2 views
0

У меня есть файл XML, который выглядит, как показано нижепоиск ключей и замена значений в XML

<name>abcdefg</name> 
<value>123456</value> 

Я пытаюсь написать скрипт, используя СЭД для поиска по тегу «АБВГДЕЖ», а затем заменить соответствующее значение «123456», но, к сожалению, я не могу найти логику для достижения выше. Нужна помощь!

+0

[BeautifulSoup] (https://www.crummy.com/software/BeautifulSoup/bs4/doc/) это хороший способ читать теги из html. –

+0

Как выглядит ваша структура? Является ли это ' k1 v1 k2 v2'?Или это ' k1 v1 k2 v2'? Мы не можем предоставить семантически-осознанный ответ, если мы не знаем структуру. –

+0

... и, если быть понятным, ответ, который * не является * семантически осведомленным, будет обязательно ошибкой: он не сможет отличить комментарии и разделы CDATA и литерал. –

ответ

2

Примеры данных:

cat key 
<name>abcdaaefg</name> 
<value>123456</value> 
<name>abcdefg</name> 
<value>123456</value> 
<name>abcdaaefg</name> 
<value>123456</value> 

sed решение:

sed '/abcdefg/!b;n;c<value>OLA<value>' key 

<name>abcdaaefg</name> 
<value>123456</value> 
<name>abcdefg</name> 
<value>OLA<value> 
<name>abcdaaefg</name> 
<value>123456</value> 

Для делать изменения в файле.

sed -i.bak '/abcdefg/!b;n;c<value>OLA<value>' key 

awk Решение:

awk '/abcdefg/ {print $0;getline;sub(/>.*</,">ola<")} {print $0}' key 
<name>abcdaaefg</name> 
<value>123456</value> 
<name>abcdefg</name> 
<value>ola</value> 
<name>abcdaaefg</name> 
<value>123456</value> 

Найдите строку, содержащую abcdefg и затем выполните следующие действия:
1. печати, линия,
2.move к следующей строке и внутри заменяющие значения html для чего-то другого. Здесь я заменил 123456 на ola.

+0

Привет, Спасибо за быстрый ответ. Но как заменить текст в файле. – user3198755

+0

использовать 'sed -i', это называется замена места и внесет изменения в ваш исходный файл. Если вы хотите сохранить резервную копию своего файла, тогда 'sed -i.bak' –

+0

Чтобы улучшить ответ, вы можете прояснить' '/ abcdefg /! B; n; c OLA '' –

0

Всякий раз, когда у вас есть tag-> пары значений в данных, это хорошая идея, чтобы создать tag-> массив значений в коде:

$ awk -F'[<>]' '{tag=$2; v[tag]=$3} tag=="value" && v["name"]=="abcdefg" {sub(/>.*</,">blahblah<")} 1' file 
<name>abcdefg</name> 
<value>blahblah</value> 
+0

Этот код не очень хорошо себя ведет с точки зрения соответствия XML. Например, предположение об одном элементе на строку означает, что это сильно испортится для огромного массива хорошо сформированных документов; также нет признания того, комментируется ли контент. Кроме того, в XML существуют обстоятельства, в которых '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'могут' –

+0

Согласовано. Похоже, что большинство вопросов, которые мы приводим здесь о разборе XML, действительно касаются разбора XML, используемого очень ограниченным образом, и поэтому awk или другие решения, как правило, адекватны, но вы можете сделать тот же случай для не цитирования переменных оболочки и т. Д., Поэтому YMMV. –

0

Используйте инструмент XML-осознанным. Это сделает ваш подход более надежным: это означает, что крошечные изменения в текстовом описании (например, добавленные или удаленные новые строки или дополнительные атрибуты, добавленные в существующий элемент) не нарушат ваш скрипт.

Предполагая, что структура вашей входной выглядит следующим образом (с бытием в рамках одного родительского элемента, здесь называется item, определяя отношения между name и value):

<config> 
    <item><name>abcdef</name><value>123456</value></item> 
    <item><name>fedcba</name><value>654321</value></item> 
</config> 

... Вы можете редактировать его как так:

# edit the value under an item having name "abcdef" 
xmlstarlet ed -u '//item[name="abcdef"]/value' -v "new-value" 

Если вместо того, чтобы это так (с упорядоченность между парами имя/значение с описанием их отношения):

<config> 
    <name>abcdef</name><value>123456</value> 
    <name>fedcba</name><value>654321</value> 
</config> 

... то вы можете изменить его, как так:

# update the value immediately following a name of "abcdef" 
xmlstarlet ed -u '//name[. = "abcdef"]/following-sibling::value[1]' -v new-value 
Смежные вопросы