2009-06-25 8 views
1

Я новичок в оболочке Linux, и я не могу понять регулярное выражение.Сценарий оболочки для извлечения определенных полей из файлов XML

Вот мой вопрос: У меня есть каталог с именем /var/visitors и в этом каталоге, у меня есть каталоги как a, b, c, d. В каждом из этих каталогов есть файл с именем list.xml и здесь, к примеру, содержание list.xml от /var/visitors/a:

<key>Name</key> 
<string>Mr Jones</string> 
<key>ID</key> 
<string>51</string> 
<key>Len</key> 
<string>53151334</string> 

То, что я хочу сделать, это объединить Name поля с соответствующей строкой и объединить поле ID с соответствующей строкой. Мне не нужны никакие другие поля.

Name: Mr Jones 
ID: 51 
--- 
Name: Ms Maggie 
ID: 502 

Вот что я, как далеко я получил:

cd /var/visitors 
find -name "list.xml" | xargs grep ????? 

Пожалуйста, помогите.

+0

GREP звучит как неправильный инструмент для этого. Подумайте о создании XSLT для этого –

+0

не кто-нибудь, способный написать это в sed? – GuleLim

ответ

0

Grep не поможет вам здесь, вам нужно будет использовать что-то вроде sed или awk.

+0

хорошо, мой друг сказал мне использовать один из них. хотя я читал man-страницы, я не мог придумать решение :( – GuleLim

+0

, потому что он не может этого сделать, я надеюсь, что кто-то еще может показать вам, как это сделать с помощью sed или awk, потому что я занят сейчас, если Я получаю перерыв, и никто не ответил, я покажу вам, как это сделать. – hhafez

+0

ОК, спасибо за внимание, hhafez. – GuleLim

0

Это реально грязный, но если вы уверены, что они находятся в формате они, вы могли бы пролить некоторый Perl вместе, чтобы разобрать его ... что-то вроде

for (<STDIN>) { 
    if (/<key>([^<]*)</) { print $1 . " : "; } 
    if (/<string>([^<]*)</) { print $1 . "\n"; } 
} 

, что не может быть совершенным, но близко к достижению того, что вы ищете. Я уверен, что есть, вероятно, некоторый модуль perl, который будет анализировать XML для вас тоже, но для такой некомплексной схемы, я думаю, с вами все будет в порядке.

+0

Как я могу изменить это так, чтобы он не принимал атрибуты, отличные от имени и id во внимание – GuleLim

+0

XML-документ кажется довольно неструктурированным :) Попробуйте изменить его на ИМЯ Mr Jones например. Таким образом, это намного проще обработать. –

+0

Согласен, XML плохо структурирован. Если вы можете его изменить, вы также можете сделать это правильно: Mr. Jones

0

Если у вас есть файл foo.bar, содержащий следующий текст:

<key>Name</key> 
<string>Mr Jones</string> 
<key>ID</key> 
<string>51</string> 
<key>Len</key> 
<string>53151334</string> 

что-то, как это будет работать:

$ awk -F '[<>]' '{if (FNR%2==1) {printf "%s: ",$3} else {print $3}}' foo.bar 
Name: Mr Jones 
ID: 51 
Len: 53151334 

Если это не совсем то, что Вы желаете, обуви рожок он также отвечает вашим конкретным требованиям.

2

Не шикарно, но это будет работать:

find -name "list.xml" | xargs cat | tr -d "\n" | sed 's/<\/string>/\n/g' | sed 's/<\/key>/: /g' | sed 's/<[^>]*>//g' | egrep "Name:|ID:" | sed 's/Name: /---\nName: /g' 

В основном он делает это:

  • удалить все переводы строк
  • положить каждую пару ключей значение в отдельной строке
  • надстройке: разделитель
  • удалить все содержимое элемента (между < и>)
  • сохранить только имя и ID поля (падение всех остальных)
  • добавить --- Сепаратор

Пример вывода:

--- 
Name: Greg 
ID: 52 
--- 
Name: Amy 
ID: 53 
--- 
Name: Mr Jones 
ID: 51 
0

я не включил в разделительную линию, потому что я не был конечно, если вы этого хотели или это был просто артефакт использования grep. Это достаточно просто добавить его в:

find -name "list.xml" | xargs awk -F '[<>]' -f xml.awk < in.dat 

И содержание xml.awk:

$2 != "string" { K=$3 } 
$2 == "string" { if ((K == "Name") || (K == "ID")) print K ": " $3 }