LINUX.ORG.RU

распарсить xml в bash

 , ,


0

3

Есть файл в котором две группы тегов:

<Vars>
<Var id="numberVar" address="number" name="name" dir="in/out..."/>
...
</Vars/
<Events>
<Event id="numberId" VarId="numberVar" .../>
</Events>
Надо что бы посредством bash в блок Event поле VarId попали номера из Var id. Прошу помощи.

Перемещено mono из talks

★★★★★

всё зависит от размера.

Надо что бы посредством bash в блок Event поле VarId попали номера из Var id.

просто рандомно напихать, да? Или тупо «первый в первый»? Или?

emulek
()

Ты решил регуляркой попарсить? Может инструмент какой взять? xmlstarlet как та поживает, живой ещё? Ну или взять нормальный ЯП.

Deleted
()

если по порядку, то

1. пронумеровать файл, все vars от нуля, и все event

2. отсортировать

3. читать по 2 строчки за раз, и обрабатывать в цикле весь файл

4. убрать нумерацию

emulek
()
Ответ на: комментарий от Deleted

Может инструмент какой взять? xmlstarlet как та поживает, живой ещё? Ну или взять нормальный ЯП.

ИМХО будет дольше. И писать дольше и работать.

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

В скриптовом языке вроде питона или руби это вполне может вертать libxml, так что дольше это вряд ли. Дольше писать это если только буквы считать. Думать всё равно больше времени. Зато «ненужных» и «неправильных» файлов, как любят говорить некоторые башеписцы на файлы вроде -rf или с пробелами, не будет :}

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

В скриптовом языке вроде питона или руби это вполне может вертать libxml

не в этом случае. Слишком простая замена.

башеписцы на файлы вроде -rf или с пробелами, не будет :}

ну если ты(ТС) не умеет и/или не хочет в баш, то да, не взлетит.

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

Вот всегда у вас там просто, а потом реальные данные оказываются немного невписывающимися в регулярку и понеслась :)

Deleted
()
Ответ на: комментарий от emulek

Кстати об умении в баш. Он целиком состоит из способов выстрелить себе в ногу. Контрпродуктивно писать на нём.

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

Вот всегда у вас там просто, а потом реальные данные оказываются немного невписывающимися в регулярку и понеслась :)

значит плохая регулярка. Их тоже нужно уметь готовить.

Кстати об умении в баш. Он целиком состоит из способов выстрелить себе в ногу. Контрпродуктивно писать на нём.

просто необходимо эти способы знать. И их, кстати, не больше, чем в других ЯП. (исключая C/C++, там на каждый оператор, ключевое слово, тип, и т.п. штук по 20 ub в среднем, всего Over9000).

Собственно, на bash просто нужно научится кавычки расставлять, и не мешать типы(т.е. числа и строки. Хотя это и одно и то же). Вот и вся специфика.

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

просто необходимо эти способы знать. И их, кстати, не больше, чем в других ЯП.

Ой, да ладно, сколько там способов выстрелить в ногу банальным рекурсивным обходом по файлам? Туча. Тут недавно кто-то ссылку постил, жаль не сохранилась %)

Собственно, на bash просто нужно научится кавычки расставлять, и не мешать типы(т.е. числа и строки. Хотя это и одно и то же). Вот и вся специфика.

Этого недостаточно для упомянутого выше рекурсивного обхода файлов с учётом того, что в них могут быть пробелы и они могут начинаться с произвольных символов :} В баше нет нормальных типов, есть только полтора ущербных костыля.

Deleted
()

Как-то парсил. Как - не помню уже.

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

Этого недостаточно для упомянутого выше рекурсивного обхода файлов с учётом того

Рекурсивно find нормально обойдёт.

turtle_bazon ★★★★★
()

вносите пример выходных данных

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

Я осилил shell. Именно поэтому я использую его как язык для описания сценариев и не пытаюсь использовать для чего-то ещё. Но наркоманы вроде тебя этого почему-то не понимают. И получается dracut(8). Или ещё что похуже.

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

Ой, да ладно, сколько там способов выстрелить в ногу банальным рекурсивным обходом по файлам? Туча. Тут недавно кто-то ссылку постил, жаль не сохранилась %)

ты просто винтовку не тем концом взял. Так ты не только в ногу можешь выстрелить… Читай про findutils (find, xargs, slocate).

Этого недостаточно для упомянутого выше рекурсивного обхода файлов с учётом того, что в них могут быть пробелы и они могут начинаться с произвольных символов :} В баше нет нормальных типов, есть только полтора ущербных костыля.

1. пробелы это не проблема

2. «произвольные символы» это ты про "-", да? Дык это проблема тех утилит, которые ты из баша на любой чих вызываешь. Если ты настолько альтернативно одарённый, что называешь файлы "-", то освой для себя --.

3. типы в баше не нужны, это не его ниша. Если тебе нужны типы, и ты пишешь на баш, то ты явно что-то сделал не так.

emulek
()
Ответ на: комментарий от kirk_johnson

Я осилил shell. Именно поэтому я использую его как язык для описания сценариев и не пытаюсь использовать для чего-то ещё.

ТСу и нужен сценарий, ему не нужна ручная работа, он хочет написать сценарий, который это сделает за него.

Но наркоманы вроде тебя этого почему-то не понимают.

Патрика ещё забыл в «наркоманы» записать. В Slackware Linux половина системных утилит на bash.

Или ещё что похуже.

юниты для systemd?

emulek
()
Ответ на: комментарий от kirk_johnson

Я осилил shell

Нет. И никогда не осилишь. Это ЯП для программиста, но не для пистон-секретутки.

anonymous
()

inb4: грамматики, regex, случаи на которых не работает;
поэтому just4fun

% cat a
<Vars>
<Var id="numberVar1" address="number" name="name" dir="in/out..."/>
<Var id="numberVar2" address="number" name="name" dir="in/out..."/>
<Var id="numberVar3" address="number" name="name" dir="in/out..."/>
<Var id="numberVar4" address="number" name="name" dir="in/out..."/>
</Vars>
<Events>
<Event id="numberId" VarId="numberVar" .../>
</Events>
% perl -ple 'push @a => /<Var id="(\w+)"/ if /<Vars>/.../<\/Vars>/; map { print "<Event id=\"IDontGetAboutThisField\" VarId=\"$_\" .../>"} @a if /<\/Events>/;' a
<Vars>
<Var id="numberVar1" address="number" name="name" dir="in/out..."/>
<Var id="numberVar2" address="number" name="name" dir="in/out..."/>
<Var id="numberVar3" address="number" name="name" dir="in/out..."/>
<Var id="numberVar4" address="number" name="name" dir="in/out..."/>
</Vars>
<Events>
<Event id="numberId" VarId="numberVar" .../>
<Event id="IDontGetAboutThisField" VarId="numberVar1" .../>
<Event id="IDontGetAboutThisField" VarId="numberVar2" .../>
<Event id="IDontGetAboutThisField" VarId="numberVar3" .../>
<Event id="IDontGetAboutThisField" VarId="numberVar4" .../>
</Events>
% # Что бы перезаписать файл, то:
% perl -i -ple 'push @a => /<Var id="(\w+)"/ if /<Vars>/.../<\/Vars>/; map { print "<Event id=\"IDontGetAboutThisField\" VarId=\"$_\" .../>"} @a if /<\/Events>/;' a

anonymous
()
Ответ на: комментарий от Komintern
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="*">
                <xsl:copy select="." />
        </xsl:template>
        <!-- IdentityTransform -->
        <xsl:template match="/ | @* | node()">
                <xsl:copy>
                        <xsl:apply-templates select="@* | node()" />
                 </xsl:copy>
         </xsl:template>
         <xsl:template match="Events">
                 <Events>
                         <xsl:apply-templates select="*" />
                         <xsl:apply-templates select="../Vars/Var" mode="vars2events" />
                 </Events>
         </xsl:template>
         <xsl:template match="Var" mode="vars2events">
                 <Event id="who knows" VarId="{current()/@id}" />
         </xsl:template>
</xsl:stylesheet>
xmlstarlet tr tr.xslt a.xml | xmllint --format -
<?xml version="1.0"?>
<root>
  <Vars>
    <Var id="numberVar1" address="number" name="name" dir="in/out..."/>
    <Var id="numberVar2" address="number" name="name" dir="in/out..."/>
    <Var id="numberVar3" address="number" name="name" dir="in/out..."/>
    <Var id="numberVar4" address="number" name="name" dir="in/out..."/>
  </Vars>
  <Events>
    <Event id="numberId" VarId="numberVar"/>
    <Event id="who knows" VarId="numberVar1"/>
    <Event id="who knows" VarId="numberVar2"/>
    <Event id="who knows" VarId="numberVar3"/>
    <Event id="who knows" VarId="numberVar4"/>
  </Events>
</root>
anonymous
()
Ответ на: комментарий от emulek

Дык это проблема тех утилит, которые ты из баша на любой чих вызываешь. Если ты настолько альтернативно одарённый, что называешь файлы "-"

Не программа плохая, пользователи плохие. Типикал баш-программер.

anonymous
()
Ответ на: комментарий от emulek

Системные утилиты друг-другу рознь. Ротация логов, например, вполне реализуема на shell. Потому что проверить время, размер и передвинуть файл задача вполне решаемая. Настройки всяких параметров системы тоже можно написать на shell. Сканирование SCSI хостов, например. А вот парсить текст — очень и очень плохая идея. Для этого есть много чего, начиная от awk и заканчивая perl.

Ну а насчет slackware — шлака это шлака. У них свой, особый взгляд на мир.

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

Не программа плохая, пользователи плохие. Типикал баш-программер.

дебилка, я не «баш-программер», баш мне нужен как шелл, и для написания простых скриптов в 100 строк максимум. И эти скрипты отлично работают.

emulek
()
Ответ на: комментарий от kirk_johnson

Системные утилиты друг-другу рознь. Ротация логов, например, вполне реализуема на shell. Потому что проверить время, размер и передвинуть файл задача вполне решаемая. Настройки всяких параметров системы тоже можно написать на shell. Сканирование SCSI хостов, например.

ну так и есть. За исключением logrotate(1), которую писать не нужно, она и так написана.

А вот парсить текст — очень и очень плохая идея. Для этого есть много чего, начиная от awk и заканчивая perl.

ты про sed слышал? Ей и пользуюсь.

А ТС почему-то просил на bash. Может д/з, откуда мне знать? Почему-бы не помочь?

Ну а насчет slackware — шлака это шлака. У них свой, особый взгляд на мир.

всё в порядке у меня со взглядом.

emulek
()
Ответ на: комментарий от kirk_johnson

А вот парсить текст — очень и очень плохая идея.

и чем же она плоха?

Для этого есть много чего, начиная от awk и заканчивая perl.

и sed. Все они нужны, в зависимости от способа их применения.

Deleted
()
Ответ на: комментарий от emulek

Пользователь может называть файлы с любыми разрешенными символами, которые поддерживает ФС, даже с непечатаемыми.

anonymous
()
Ответ на: комментарий от Deleted

Ой, да ладно, сколько там способов выстрелить в ногу банальным рекурсивным обходом по файлам?

тот пост напоминает рекламу про жопоруких из телемагазина.

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

и чем же она плоха?

в принципе bash хорошо справляется с простыми задачами обработки строк, типа ${X:y:z} или ${X##*/} и даже ${X/regex/sub}, но плохо продумана передача параметров, read реагирует на спецсимволы, т.е. если делать такой цикл

while read FILENAME; do
  # body
done< <(find…)
то не работает для файлов с \n в имени, она считывает до конца строки.

Как это исправить, я не знаю.

emulek
()
Ответ на: комментарий от kirk_johnson

А вот парсить текст — очень и очень плохая идея. Для этого есть много чего, начиная от awk и заканчивая perl.

А причем тут bash? sed это sed.

дык кто мне помешает юзать sed в bash?

emulek
()
Ответ на: комментарий от anonymous

Пользователь может называть файлы с любыми разрешенными символами, которые поддерживает ФС, даже с непечатаемыми.

man xargs

--null -0 Input items are terminated by a null character instead of by whitespace, and the quotes and backslash are not special (every character is taken literally). Disables the end of file string, which is treated like any other argument. Useful when input items might contain white space, quote marks, or backslashes. The GNU find -print0 option produces input suitable for this mode.

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

Как это исправить, я не знаю.

не писать так) писать в find -print0 и дальше либо exec, через пайп xargs -0 ...

ПыСы: если правильно понял о чём ты.

Deleted
()
Ответ на: комментарий от emulek

есть файл коммасепар: содержит описания стр-р:

6890,PROTECTIONS.AVR.Parent,pointer,,,,,5216,414476,4
6891,PROTECTIONS.AVR.Mod,INC,S,,,SHM,,414480,312
6892,PROTECTIONS.AVR.Mod.ctlVal,INT32,,CO,,,,414480,4
6893,PROTECTIONS.AVR.Mod.operTm,TimeStamp,,CO,,,,414484,8
6894,PROTECTIONS.AVR.Mod.origin,Originator,S,CO,,,,414492,260
6895,PROTECTIONS.AVR.Mod.origin.orCat,ENUMERATED,,,,,,414492,4
6896,PROTECTIONS.AVR.Mod.origin.orIdent,INT8U_64,E,,,,,414496,256
6897,PROTECTIONS.AVR.Mod.ctlNum,INT8U,,CO,,,,414752,4
6898,PROTECTIONS.AVR.Mod.stVal,INT32,,ST,dchg,,,414756,4
6899,PROTECTIONS.AVR.Mod.q,Quality,,ST,qchg,,,414760,4
6900,PROTECTIONS.AVR.Mod.t,TimeStamp,,ST,,,,414764,8
6901,PROTECTIONS.AVR.Mod.stSeld,BOOLEAN,,ST,dchg,,,414772,4
6902,PROTECTIONS.AVR.Mod.ctlModel,CtlModels,,RCF,,,,414776,4
6903,PROTECTIONS.AVR.Mod.minVal,INT32,,RCF,,,1,414780,4
6904,PROTECTIONS.AVR.Mod.maxVal,INT32,,RCF,,,5,414784,4
6905,PROTECTIONS.AVR.Mod.stepSize,INT32U,E,RCF,,,1,414788,4
6906,PROTECTIONS.AVR.Beh,INS,S,,,SHM,,414792,16
6907,PROTECTIONS.AVR.Beh.stVal,INT32,,ST,dchg,,,414792,4
6908,PROTECTIONS.AVR.Beh.q,Quality,,ST,qchg,,,414796,4
6909,PROTECTIONS.AVR.Beh.t,TimeStamp,E,ST,,,,414800,8
6910,PROTECTIONS.AVR.Health,INS,S,,,SHM,,414808,16
6911,PROTECTIONS.AVR.Health.stVal,INT32,,ST,dchg,,,414808,4
6912,PROTECTIONS.AVR.Health.q,Quality,,ST,qchg,,,414812,4
6913,PROTECTIONS.AVR.Health.t,TimeStamp,E,ST,,,,414816,8
6914,PROTECTIONS.AVR.SigLen,ASG,S,,,SHM,,414824,56
6915,PROTECTIONS.AVR.SigLen.setMag,AnalogueValue,,SG,,,5000;1000;0,414824,12
6916,PROTECTIONS.AVR.SigLen.units,Unit,S,RCF,,,,414836,8
6917,PROTECTIONS.AVR.SigLen.units.SIunits,ENUMERATED,,,,,5,414836,4
6918,PROTECTIONS.AVR.SigLen.units.multiplier,ENUMERATED,E,,,,0,414840,4
6919,PROTECTIONS.AVR.SigLen.minVal,AnalogueValue,,RCF,,,1000;1000;0,414844,12
6920,PROTECTIONS.AVR.SigLen.maxVal,AnalogueValue,,RCF,,,30000;1000;0,414856,12
6921,PROTECTIONS.AVR.SigLen.stepSize,AnalogueValue,E,RCF,,,1000;1000;0,414868,12
6922,PROTECTIONS.AVR.AVRSt,SPS,S,,,SHM,,414880,16
6923,PROTECTIONS.AVR.AVRSt.stVal,BOOLEAN,,ST,dchg,,,414880,4
6924,PROTECTIONS.AVR.AVRSt.q,Quality,,ST,qchg,,,414884,4
6925,PROTECTIONS.AVR.AVRSt.t,TimeStamp,E,ST,,,,414888,8
6926,PROTECTIONS.AVR.SlaveSt,SPS,S,,,SHM,,414896,16
6927,PROTECTIONS.AVR.SlaveSt.stVal,BOOLEAN,,ST,dchg,,,414896,4
6928,PROTECTIONS.AVR.SlaveSt.q,Quality,,ST,qchg,,,414900,4
6929,PROTECTIONS.AVR.SlaveSt.t,TimeStamp,E,ST,,,,414904,8

Содержит около 10000 строк, я парсю его толька на булевые значения и запихиваю их в xml :

echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > $outstream
echo "<HMIConfig05>" >> $outstream
echo "<Vars>" >> $outstream

awk -F "\"*,\"*" '/BOOLEAN/ {print "<Var id=""\042"$1"\042" "\t" "address=""\042"$1"\042" "\t" "type=""\042""$type""\042" "\t" "desc=""\042"$2"\042" "\t" "localDesc=""\042""\042" "\t" "dir=""\042""$dir""\042" "\t" "local=""\042""\042" "\t" "/>" }' file.csv >> $outstream
Далее Добавляем блок Events:
echo "</Vars>" >> $outstream
echo "<Events>" >> $outstream
awk -F "\"*,\"*" '/BOOLEAN/ {print "<Event id=""\042"$1"\042" "\t" "VarId=""\042""$VarId""\042" "\t" "name=""\042"$2"\042" "\t" "localDesc=""\042""\042" "\t" "relay=""\042""false""\042" "\t" "type=""\042""\042" "\t" "/>" }' file.csv >> $outstream
echo "</Events>" >> $outstream
Теперь надо поле VarId, заполнить значениями из Var Id

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

не писать так

я в курсе(см. прошлые мои посты). Но это для одной команды.

Лично я просто не создаю файлы с \n. А кто создаёт — ССЗБ.

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

awk -F «\»*,\«*» '/BOOLEAN/ {print «<Var id=»«\042»$1"\042" «\t» «address=»«\042»$1"\042" «\t» «type=»«\042»"$type""\042" «\t» «desc=»«\042»$2"\042" «\t» «localDesc=»«\042»"\042" «\t» «dir=»«\042»"$dir""\042" «\t» «local=»«\042»"\042" «\t» «/>» }' file.csv >> $outstream

да… ППЦ

emulek
()
Ответ на: комментарий от Deleted

xmlstarlet как та поживает, живой ещё?

Нормально поживает. Последняя версия 1.6.1 от прошлого года.

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

Я просто не пишу на этом, поэтому говорить о боли какой-то смысла нет, но выпилить скриптоту из загрузки это Поттеринг хорошо придумал :}

Deleted
()
Последнее исправление: Mystra_x64 (всего исправлений: 1)
Ответ на: комментарий от emulek

типы в баше не нужны, это не его ниша.

Тем не менее, типы данных в ограниченном виде присутствуют в BASH:

# Обычный список
declare -a list
# Хэш
declare -A hash
# Целое число
declare -i int
# Константа
declare -r const
# ...ну и, не в тему, но всё же...
# Глобальная переменная:
declare -g glob
DRVTiny ★★★★★
()
Ответ на: комментарий от Deleted

Уж больно в этом инструменте много жоп

на каждую хитровыверченную жопу найдётся…

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.