1

Для справки, я провел несколько дней, работая над этим без удачи.

Я работаю с XML-файлами с данными, содержащими что-то вроде следующего:

<row id="67581917031" name="4022" filesize="22425" file_content_id="67581868031" lastmodify_datetime="1187126570050" group_id="67581916031"/> <row id="254115371041" name="4022" filesize="49471" file_content_id="254115361041" lastmodify_datetime="1220512827666" group_id="253405951041"/> <row id="286104505041" name="4022" filesize="3802672" file_content_id="286104455041" lastmodify_datetime="1223348052489" group_id="286104504041"/> <row id="289541609041" name="4022" filesize="42235" file_content_id="264826268041" lastmodify_datetime="1223587308419" group_id="289541607041"/> <row id="306643757002" name="4022" filesize="392560" file_content_id="243411753011" lastmodify_datetime="1218251898489" group_id="67581916031"/> <row id="367316910041" name="4022" filesize="381083" file_content_id="367316830041" lastmodify_datetime="1232592570004" group_id="74169006021"/>

Если вы посмотрите внимательно, вы обнаружите, что две из этих записей имеют одинаковые "name" и "group_id". Я пытаюсь написать скрипт, который найдет эти строки и выдаст идентификатор строки, имя и идентификатор группы. Я надеялся сделать это либо использовать sed, чтобы забрать в конце каждой "строки" и вставить новую строку (\n), чтобы затем я мог использовать nl чтобы распечатать количество строк, сохранить это число в переменной, а затем использовать цикл for для запуска команды awk для сопоставления с образцом каждого идентификатора строки, имени и group_id и каким-либо образом проверяет, совпадают ли name и group_id с какими-либо другими строками, и, если они совпадают, выведите идентификатор строки и имя ,

1 ответ1

2

Если вы ищете те строки, которые имеют одинаковое name AND group_id , вы можете сделать что-то вроде этого (предполагая, что вы работаете в * nix ОС, вы не говорите в своем вопросе, вы можете просто вставить это непосредственно в командную строку ):

sed 's#/>#/>\n#g' simple_file.xml |
        perl -ne 'if(/row id=.(.+?)\".+name=.(.+?)\".+group_id=.(.+?)\"/){ 
         push @{$k{join("\t",$2,$3)}},$1;} 
         END{ 
           foreach (keys(%k)){ 
            if($#{$k{$_}}>0){
                 print "$_\t",pop @{$k{$_}},"\n" 
          } }}' 

ОБЪЯСНЕНИЕ:

  • sed 's#/>#/>\n#g' simple_file.xml : добавление новой строки после каждой записи (после каждого />) для облегчения анализа.
  • perl -ne : обрабатывать файл построчно
  • /row id= ... group_id=.(\d+)/; : используйте регулярное выражение (что обычно плохо для [X] HTML-файлов, у вас может быть кровь пушистых котят в ваших руках), чтобы получить row_id , name и group_id , они сохраняются как $1 , $2 и $3 соответственно.
  • push @{$k{join("\t",$2,$3)}},$1; Это немного сложнее. Он создает хэш массивов с именем (%k), а затем использует join для соединения name и group_id с вкладкой. Наконец, он добавляет row_id в массив. Другими словами, если ваш row_id равен 123 , ваше name 456 и ваш group_id 789 , который создаст массив и сохранит его как значение хеша %k для ключа 456 789 .

  • Блок END{} выполняется один раз, когда остальная часть файла была обработана. Он будет проходить через каждый из ключей хеша (значения которых являются массивами) и распечатывать те случаи, когда массив имеет более одной записи, другими словами, дубликаты. Функция pop возвращает последний элемент массива, в данном случае row_id .

Я запустил это на вашем примере и получил такой вывод:

4022    67581916031 306643757002
----    ----------  ------------
 |           |           |---------------> row id
 |           |---------------------------> group id
 |---------------------------------------> name

Если вы не видите ссылку во втором пункте, я просто хотел бы подчеркнуть, что вы.Должен. Никогда. Синтаксический. [X] HTML. С. Regular. Выражения.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .