Это замечательно похоже на файл XML.Настоятельно рекомендуется использовать для этой работы инструменты, связанные с XML, такие как xmlstarlet
.
При условии, что данный входной файл имеет вид:
<header>
<node>
<key>UniqueKey</key>
<foo />
<string>100</string>
</node>
<node>
<key>UniqueKey</key>
<string>101</string>
<string>200</string>
</node>
</header>
Тогда следующая команда будет обновлена какзапрошено:
$ xmlstarlet ed -u '//key[text()="UniqueKey"]/following-sibling::string[1]' \
-x '(text()+1)' file.xml
Это делает следующее:
ed
: войти в режим редактирования -u <xpath>
: обновить узлы, соответствующиеxpath
//key
: выберите любой узел с именем key
//key[text()="UniqueKey"]
: выберите любой узел с именем key
и значением "UniqueKey"
//key[text()="UniqueKey"]/following-sibling::string
: выберите первые «строковые» братья и сестры из key
, следующие за key
-x '(text()+1)'
: обновить значение выбранных узлов навыражение text()+1
Выходные данные затем определяются как:
<?xml version="1.0"?>
<header>
<node>
<key>UniqueKey</key>
<foo/>
<string>101</string> # change
</node>
<node>
<key>UniqueKey</key>
<string>102</string> # change
<string>200</string> # no change
</node>
</header>
Или, если это действительно должен быть следующий узел, то вам нужно сыграть фокусс concat
и substring
, поскольку xpath-1.0 не имеет условий.Подробнее здесь
$ xmlstarlet ed -u '//key[text()="UniqueKey"]/following-sibling::*[1]' \
-x 'substring(text()+1,1,number(name()="string")*string-length(text()+1))' file.xml
<?xml version="1.0"?>
<header>
<node>
<key>UniqueKey</key>
<foo/>
<string>100</string> # no change
</node>
<node>
<key>UniqueKey</key>
<string>102</string> # change
<string>200</string> # no change
</node>
</header>