LINUX.ORG.RU

BASH парсить XML


0

1

Есть XML вида:

<schema>
      <key>daemon/AutomaticLoginEnable</key>
      <signature>b</signature>
      <default>false</default> 
</schema>
Как заставить bash найти необходимый мне параметр daemon/AutomaticLoginEnable спуститься на 3 строки и вместо false сделать true?

★★★★★

рекурсивно grep+регексп?
афаик, нативных средств для хмл в баше нету.

etwrq ★★★★★
()

Напиши лучше скрипт на чем-то, имеющем хорошую либу для обработки XML (например, питон + xml.dom.minidom), и вызови этот скрипт из баша.

provaton ★★★★★
()
Ответ на: комментарий от provaton

не охото тянуть лишние зависимости из-за одного скрипта.

splinter ★★★★★
() автор топика

для этого придумали perl

arknir
()

Ну вывести эту строку можно так

$ cat sedtest
<schema>
      <key>daemon/AutomaticLoginEnable</key>
      <signature>b</signature>
      <default>false</default>
</schema>
$ sed -n '/<key>daemon\/AutomaticLoginEnable<\/key>/{n;n;p;}' sedtest
      <default>false</default>
Чё дальше?

adriano32 ★★★
()
Ответ на: комментарий от splinter

Пообещайте печенек тому, кто перепишет это полностью на sed. С интересом посмотрю, так как должно быть более красивое решение

zolden ★★★★★
()
Ответ на: комментарий от zolden
$ sed "`sed -n '/<key>daemon\/AutomaticLoginEnable<\/key>/{n;n;=;}' sedtest` s/false/true/" sedtest
<schema>
      <key>daemon/AutomaticLoginEnable</key>
      <signature>b</signature>
      <default>true</default>
</schema>

Давайте мои печеньки!!!

adriano32 ★★★
()
Ответ на: комментарий от adriano32

А Вот и Победитель!

$ sed '/<key>daemon\/AutomaticLoginEnable<\/key>/{n;n;s/false/true/;}' sedtest
<schema>
      <key>daemon/AutomaticLoginEnable</key>
      <signature>b</signature>
      <default>true</default>
</schema>
adriano32 ★★★
()
Ответ на: комментарий от zolden

как задать полное соответствие шаблону?
есть два значения AutomaticLoginEnable и AutomaticLogin
если делать awk '/AutomaticLogin/ file то попадает оба значения, а мне необходимо строгое соответствие шаблону.

splinter ★★★★★
() автор топика
Ответ на: комментарий от splinter

Вот этот вариант самый лучший

А если есть два значения AutomaticLoginEnable и AutomaticLogin, то

sed '/<key>daemon\/AutomaticLoginEnable<\/key>\|<key>daemon\/AutomaticLogin<\/key>/{n;n;s/false/true/;}' sedtest
<schema>
      <key>daemon/AutomaticLogin</key>
      <signature>b</signature>
      <default>true</default>
</schema>

adriano32 ★★★
()
Ответ на: комментарий от adriano32

Это после того, как я в sedtest заменил AutomaticLoginEnable на AutomaticLogin, конечно, потому и вывелось <key>daemon/AutomaticLogin</key>

adriano32 ★★★
()
Ответ на: комментарий от adriano32

Ну это все хорошо, а что будет, если кто-то случайно вставит пустую строку? Или наоборот, разместист signature и default в одной строке? Очень ненадежное решение, ИМХО.

provaton ★★★★★
()
Ответ на: комментарий от provaton

Решение zolden'a точно такое же ненадёжное. И да, читай поставленную задачу
«спуститься на 3 строки и вместо false сделать true? »
Это предполагает, что ТС уверен на 100%, что третьей строчкой будет то, что ему нужно.

Что предлагаешь?

adriano32 ★★★
()
Ответ на: комментарий от adriano32

Что предлагаешь?

Я свое предложение написал во втором посте. Оно намного тяжеловеснее чем твое, но будет работать для любого валидного XML. Выбирать ТСу, конечно, думаю он понимает плюсы и минусы каждого предложенного решения.

provaton ★★★★★
()

Может, просто заюзать xmlstarlet?

x3al ★★★★★
()
Ответ на: комментарий от Tanger

Я об inline знаю, на практике иногда лучше записать в новую версию файла, чем править оригинал. ТС сам решит. Так по крайней мере выхлоп очевиден.

adriano32 ★★★
()
Ответ на: комментарий от Tanger

Есть даже такие удобные штуки.

Круто, спасибо. Будет время - подучу регэкспы с этой штукой.

Axon ★★★★★
()
Ответ на: комментарий от Tanger

В KWrite конструктор регекспов с предпросмотром и проверкой встроен в редактор и может быть вызван из диалога замены/поиска.

adriano32 ★★★
()
Ответ на: А Вот и Победитель! от adriano32

А где тут собственно баш?

#!/bin/sh

if [ $# -lt 3 ] ; then
    echo "Usage: $0 /path/to/fckd.xml key value"
    exit 1
fi

exec <$1

unset __schema_block
unset __key_ok

while read line; do
    if [[ $line = *\<schema\>* ]]; then 
        __schema_block=yes
    elif [[ $line = *\</schema\>* ]]; then
        unset __schema_block
        unset __key_ok
    elif [ ! -z "$__schema_block" ] && [[ $line = *\<key\>* ]]; then
        if [[ $line = *$2* ]]; then
            __key_ok=yes
        fi
    elif [ ! -z "$__key_ok" ] && [[ $line = *\<default\>*\</default\>* ]]; then
        line="<default>$3</default>"
    fi
    echo $line
done

Как то так..

vasily_pupkin ★★★★★
()
Ответ на: комментарий от vasily_pupkin

ОП: splinter **** (20.07.2011 13:06:49)
ответ: vasily_pupkin *** (21.07.2011 18:11:02)

Ого! Больше суток писал, но это по-настоящему круто, мой респект!

adriano32 ★★★
()
Ответ на: комментарий от adriano32

Лол. Школьники в отпуске штоле. Чоэта вчерашние треды на первой странице (%

vasily_pupkin ★★★★★
()

Просили парсинг XML из bash? Получите, распишитесь. :)

#!/bin/bash

ruby -e '
  require "xmlsimple"
  data = XmlSimple.xml_in(STDIN.read)
  # делаем с data что-нибудь полезное
' < somedata
geekless ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.