понедельник, 14 апреля 2014 г.

Парсинг и вывод заданным форматом всех .xml файлов, начиная с указанной директории

1) Написать команду или скрипт, просматривающий все *.xml файлы в директории.

Формат файлов:

<FirstName>john</FirstName>
<MiddleInitial>D</MiddleInitial>
<LastName>Smith</LastName>

<Delivered>
<Date>2014-01-31</Date>
</Delivered>

Имена могут иметь пробелы, верхний или нижний регистр, включать - или '.

Необходимо пропарсить все файлы и вывести данные в файл:

firstname middleinitial lastname | delivered date | filenameitwaslocated.xml
firstname middleinitial lastname | delivered date | filenameitwaslocated.xml


1.1) Разбираю несколько примеров, вот один из них:

grep -v ^[[:space:]]*\# $1 | grep -v ^[[:space:]]*\; | grep -v ^$

^ - начало строки
$ - конец строки
[:space:] - соответствует пробельным символам (пробел и горизонтальная табуляция)
[] - один из символов, указанных в скобках

в чем отличие ? от . - в том что точку можно указать просто, а вопрос надо экранировать, иначе он воспринимается как символ вопрос

2) Пишу свой скрипт.

2.1) Создаю файл с данными:
#   3
  ##
<FirstName>j o h n</FirstName>
<MiddleInitial>-D-</MiddleInitial>
<LastName>S-mith'</LastName>

<Delivered>
<Date>2014-01-31</Date>
</Delivered>

2.2) Затем в исполняемый файл пишу команду и передаю параметром файл данных:

/bin/echo `grep -o '>.*<' $1 | sed 's/<\|>//g'`
выдает
j o h n -D- S-mith' 2014-01-31
как теперь сделать
j o h n -D- S-mith' | 2014-01-31 | filenameitwaslocated.xml

echo `grep -o '>.*<' $1`"$1"|(sed 's/>\(.*\)<.>\(.*\)<.>\(.*\)<.>\(.*\)<\(.*\)/\1 \2 \3 | \4 | \5/')
выдает
j o h n -D- S-mith' | 2014-01-31 | cat_xml.input

2.3) написать что ли как оно работает...

grep построчно парсит файл, передаваемый параметром $1
-o - выдавать только то что соответствует шаблону
получаются строки вида >то_что_между<
echo убирает с конца каждой строки перевод на новую строку, выдает все строки одной строкой и добавляет в конец имя переданного файла "$1"
sed парсит строку по шаблону />\(.*\)<.>\(.*\)<.>\(.*\)<.>\(.*\)<\(.*\)/ и возвращает 5 значений (.*\), которые я потом вывожу, форматируя /\1 \2 \3 | \4 | \5/

2.4) Двигаюсь дальше. Создаю несколько файлов *.xml

find ./ -name '*.xml' -exec ./cat_xml {} > ./output \;
cat ./output
4 o h n -D- S-4mith' | 2014-01-34 | ./cat_xml4.xml
55j o h n 55 S-mith55' | 2014-01-35 | ./cat_xml5.xml
j o h n2 D- Smith' | 2014-01-32 | ./cat_xml2.xml
4 o h n -D- S-4mith' | 2014-01-34 | ./222/cat_xml4.xml
55j o h n 55 S-mith55' | 2014-01-35 | ./222/cat_xml5.xml
j o h n2 D- Smith' | 2014-01-32 | ./222/cat_xml2.xml
j o h n -D- S-mith' | 2014-01-31 | ./222/cat_xml1.xml
j3o3h3n D3 S-mith3 | 2014-01-33 | ./222/cat_xml3.xml
j o h n -D- S-mith' | 2014-01-31 | ./cat_xml1.xml
j3o3h3n D3 S-mith3 | 2014-01-33 | ./cat_xml3.xml

3) Использованные ресурсы:
http://rus-linux.net/MyLDP/BOOKS/abs-guide/flat/abs-book.html
http://citforum.ru/operating_systems/manpages/bash/BASH.1_2.shtml#expansion
http://www.theunixschool.com/2013/02/sed-examples-replace-delete-print-lines-csv-files.html
http://unix.stackexchange.com/questions/64645/text-between-two-tags
http://stackoverflow.com/questions/8476329/get-string-between-and-linux-directory

Комментариев нет:

Отправить комментарий