2013-06-29 3 views
1

у меня есть большой XML-файл с кучей определений таблиц базы данных, которые выглядят следующим образом:изменять XML-тег с конкретным шаблоном с помощью инструментов REGEX

table name="dbname.tablename" lots of text here> 

Я хотел бы заменить закрывающую скобку в каждой соответствующей линии (не все линии начинаются с table name=""), так что исходная строка сохраняется, но slonyId="number" прилагается до >. Для того, чтобы сделать вещи немного более сложным, я хотел бы число slonyId будет увеличиваться, начиная с 0, так что если у меня есть 1000 определений таблицы, первый выглядит следующим образом:

table name="dbname.tablename" lots of text here slonyid="0"> 

И последний выглядит например:

table name="dbname.tablename" lots of text here slonyId="999"> 

Каков наилучший подход к решению этой проблемы?

Заранее благодарен!

+0

Как вы распознающий строку, если 'имя таблицы =' ins't гарантированно быть там? Является единственной идентифицирующей функцией '>'? – FDinoff

+0

Каждая строка, о которой я забочусь, начинается с «table name =» В файле много других строк, но некоторые начинают с «имени индекса» или чего-то еще. Мне не нужно изменять эти строки. – user2533865

ответ

3

Добавление раствора из JS:

awk -F'>' '/table name/{$NF="slonyid="q x++ q FS}1' q='"' inputFile 

Попробуйте это:

awk -F'>' '/table name/{print $(NF-1)" slonyid""=""\""NR-1"\""">"}' inputFile 

Добавление тест:

$ cat temp.txt 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 
table name="dbname.tablename" lots of text here> 


$ awk -F'>' '/table name/{print $(NF-1)" slonyid""=""\""NR-1"\""">"}' temp.txt 
table name="dbname.tablename" lots of text here slonyid="0"> 
table name="dbname.tablename" lots of text here slonyid="1"> 
table name="dbname.tablename" lots of text here slonyid="2"> 
table name="dbname.tablename" lots of text here slonyid="3"> 
table name="dbname.tablename" lots of text here slonyid="4"> 
table name="dbname.tablename" lots of text here slonyid="5"> 
table name="dbname.tablename" lots of text here slonyid="6"> 
table name="dbname.tablename" lots of text here slonyid="7"> 
table name="dbname.tablename" lots of text here slonyid="8"> 
table name="dbname.tablename" lots of text here slonyid="9"> 
table name="dbname.tablename" lots of text here slonyid="10"> 
table name="dbname.tablename" lots of text here slonyid="11"> 
table name="dbname.tablename" lots of text here slonyid="12"> 
table name="dbname.tablename" lots of text here slonyid="13"> 
table name="dbname.tablename" lots of text here slonyid="14"> 
+0

Я не совсем понимаю эту команду, и я не уверен, как она работает. Я думаю, что -F идентифицирует> как разделитель полей. Не могли бы вы уточнить? Тот факт, что я не вижу «slonyID =» в любом месте вашего решения, заставляет меня думать, что ваше решение не решит мою проблему. Благодаря! – user2533865

+0

@ user2533865 Я добавил тест, надеюсь, что это поможет. – Amit

+0

о, ничего себе. Это гениально! Спасибо! – user2533865

0

ВИМ решение

Использовать глобальный найти table name= в линии. и замените > на эту строку с помощью slonyId="number">. Вы можете сделать это, используя следующие две строки.

:let i = 0 
:g/^table name=/s/>/\='slonyId="' . i . '"' . submatch(0)/ | let i=i+1 

Первая строка инициализирует i 0. заменителем берет первый элемент этого списка каждый раз, когда он делает матч и использует конкатенации для создания правильной строки. Затем после замены i будет увеличиваться. Так что следующая замена получает следующее число в последовательности.

1

Это Perl один лайнер будет делать трюк, если я правильно понимаю ваш вопрос:

perl -pi.bak -e 'BEGIN {$count=0}; if (/^table name=/) { s/^(table name=.*)>$/$1 slonyId="$count">/; $count++}' inputFile.xml 

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

perl -pi.bak -e 

Это инициализирует $count переменную:

BEGIN {$count=0}; 

Это увеличивает количество и делает замену вы просили:

if (/^table name=/) { s/^(table name=.*)>$/$1 slonyId="$count">/; $count++} 

Тогда просто предоставить список имен файлов в конце:

inputFile.xml 

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

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

not a table name="dbname.tablename" lots of text here> 

И решение Amit будет добавить slonyId для каждой строки, а не только для строк, начинающихся с «имени таблицы».

2

Код для GNU :

sed = file|sed 'N;s/\n/\t/;/\S\+\s\+table name/!d'|sed =|sed 'N;s/\n/\t/;s/\(\S\+\)\s\+\([^>]\+\)>/\2 slonyid="\1">/;s#\(\S\+\)\s\+\(.*\)#\1 s/.*/\2/#'|sed -f - file 

Чистый sed решение с 4 трубами.

 
$cat file 
table name="dbname.tablename" lots of text AAA here> 
index name="dbname.tablename" lots of text XXX here> 
index name="dbname.tablename" lots of text YYY here> 
index name="dbname.tablename" lots of text ZZZ here> 
table name="dbname.tablename" lots of text BBB here> 
index name="dbname.tablename" lots of text XXX here> 
index name="dbname.tablename" lots of text YYY here> 
table name="dbname.tablename" lots of text CCC here> 
index name="dbname.tablename" lots of text XXX here> 
table name="dbname.tablename" lots of text DDD here> 
index name="dbname.tablename" lots of text XXX here> 
index name="dbname.tablename" lots of text YYY here> 
index name="dbname.tablename" lots of text ZZZ here> 
table name="dbname.tablename" lots of text EEE here> 
index name="dbname.tablename" lots of text XXX here> 
index name="dbname.tablename" lots of text YYY here> 
table name="dbname.tablename" lots of text FFF here> 
index name="dbname.tablename" lots of text XXX here> 
index name="dbname.tablename" lots of text YYY here> 
index name="dbname.tablename" lots of text ZZZ here> 

$sed = file|sed 'N;s/\n/\t/;/\S\+\s\+table name/!d'|sed =|sed 'N;s/\n/\t/;s/\(\S\+\)\s\+\([^>]\+\)>/\2 slonyid="\1">/;s#\(\S\+\)\s\+\(.*\)#\1 s/.*/\2/#'|sed -f - file 
table name="dbname.tablename" lots of text AAA here slonyid="1"> 
index name="dbname.tablename" lots of text XXX here> 
index name="dbname.tablename" lots of text YYY here> 
index name="dbname.tablename" lots of text ZZZ here> 
table name="dbname.tablename" lots of text BBB here slonyid="2"> 
index name="dbname.tablename" lots of text XXX here> 
index name="dbname.tablename" lots of text YYY here> 
table name="dbname.tablename" lots of text CCC here slonyid="3"> 
index name="dbname.tablename" lots of text XXX here> 
table name="dbname.tablename" lots of text DDD here slonyid="4"> 
index name="dbname.tablename" lots of text XXX here> 
index name="dbname.tablename" lots of text YYY here> 
index name="dbname.tablename" lots of text ZZZ here> 
table name="dbname.tablename" lots of text EEE here slonyid="5"> 
index name="dbname.tablename" lots of text XXX here> 
index name="dbname.tablename" lots of text YYY here> 
table name="dbname.tablename" lots of text FFF here slonyid="6"> 
index name="dbname.tablename" lots of text XXX here> 
index name="dbname.tablename" lots of text YYY here> 
index name="dbname.tablename" lots of text ZZZ here> 
+0

стартовый номер - '1', а не' 0' - imo, это не может быть исправлено. – Endoro

0

Вы никогда не должны редактировать файлы XML, используя линейные манипуляции строк. XML не структурирован так. Всегда используйте правильный XML-анализатор, как в Perl XML::LibXML:

#!/usr/bin/env perl 

use strict; 
use warnings; 
use XML::LibXML; 

my $xml = XML::LibXML->new->parse_file('/path/to/input.xml'); 

my $i = 0; 
$_->setAttribute('slonyId', $i++) for $xml->findnodes('//table'); 

$xml->toFile('/path/to/output.xml') 
+0

Фрагмент OP, размещенный недействителен XML, поэтому, если вы попытались с тем, что это неудивительно, вы получили сообщение об ошибке. –

+2

XML, или, по крайней мере, OP утверждал, что это было. –

+0

Я сказал * не должен *, а не * не может *. И это на самом деле довольно просто: если ваш ввод XML: используйте синтаксический анализатор XML. XML: используйте все, что подходит. Поскольку только OP может уточнить, действителен ли файл X ML Я не собираюсь продолжать этот бессмысленный аргумент. –