В вашем коде есть пара вещей, которые на самом деле не имеют смысла, например, использование Data :: Dumper и синтаксический анализ вывода с помощью регулярного выражения. Я не собираюсь проверять ваш код, так как он не является верным c в переполнении стека, но вместо этого я дам вам альтернативное решение и проведу вас через него.
Обратите внимание, что XML: : Простой не великий инструмент. Его использование не рекомендуется, потому что оно плохо работает с определенными случаями. Но для вашей очень простой структуры XML она будет работать, поэтому я сохранил ее.
use strict;
use warnings;
use XML::Simple;
use feature 'say';
# read XML file and reorganise it for easier use
my $data;
foreach my $run (@{XMLin(\*DATA)->{Run}}) {
$data->{$run->{DESIGN_ID}}->{$run->{PROCESS_ID}} =
{map { $_ => 1 } @{$run->{RegisterList}->{Register}}};
}
# read the text file - I've skipped the read
my @user_input = qw(
L84A:FIP:70:155:15:18:
L83A:55FIP:70:155:15:
);
foreach my $line (@user_input) {
chomp $line
; # we don't need this in my example, but you do when you read from a file
my ($design_id, $process_id, @register_ids) = split /:/, $line;
# extra error checking just in case
if (not exists $data->{$design_id}) {
say "$design_id does't exist in data";
next;
}
if (not exists $data->{$design_id}->{$process_id}) {
say "$design_id: doesn't have $process_id";
next;
}
say "$design_id:";
say " $process_id";
foreach my $register_id (@register_ids) {
if (exists $data->{$design_id}->{$process_id}->{$register_id}) {
say " $register_id - existing register ID";
}
else {
say " $register_id - no existing register ID";
}
}
}
__DATA__
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Sigma>
<Run>
<DESIGN_ID>L83A</DESIGN_ID>
<PROCESS_ID>55FIP</PROCESS_ID>
<RegisterList>
<Register>70</Register>
<Register>155</Register>
</RegisterList>
</Run>
<Run>
<DESIGN_ID>L83A</DESIGN_ID>
<PROCESS_ID>FRP</PROCESS_ID>
<RegisterList>
<Register>141</Register>
<Register>149</Register>
<Register>151</Register>
</RegisterList>
</Run>
<Run>
<DESIGN_ID>L84A</DESIGN_ID>
<PROCESS_ID>55FIP</PROCESS_ID>
<RegisterList>
<Register>70</Register>
<Register>155</Register>
</RegisterList>
</Run>
</Sigma>
Я сделал несколько предположений.
Вы уже знаете, как читать текстовый файл, поэтому я вставил его в массив построчно. Однако у вашего кода чтения файлов есть некоторые проблемы, вы должны использовать трехэлементные открытые и лексические дескрипторы файлов. Ваш вызов open
должен выглядеть следующим образом:
open my $fh, '<', $filename or die "$!: error...";
В качестве альтернативы рассмотрите возможность использования Path :: Tiny .
I'm взять файл XML из раздела __DATA__
. Это похоже на файловый дескриптор.
Итак, давайте посмотрим на мой код.
Когда мы читаем структуру XML, она выглядит прямо из XMLin
.
\ {
Run [
[0] {
DESIGN_ID "L83A",
PROCESS_ID "55FIP",
RegisterList {
Register [
[0] 70,
[1] 155
]
}
},
[1] {
DESIGN_ID "L83A",
PROCESS_ID "FRP",
RegisterList {
Register [
[0] 141,
[1] 149,
[2] 151
]
}
},
[2] {
DESIGN_ID "L84A",
PROCESS_ID "55FIP",
RegisterList {
Register [
[0] 70,
[1] 155
]
}
}
]
}
Это не очень полезно для того, что мы планируем делать, поэтому мы должны изменить его. Я хочу использовать exists
для ссылок ha sh позже, чтобы упростить поиск, если есть совпадения для идентификаторов, которые мы ищем. Это называется lookup ha sh. Мы можем пропустить ключ ->{Run}
, так как XML :: Simple объединяет все элементы <Run>
в ссылку на массив, а тег <Sigma>
просто пропускается, потому что это элемент root.
Каждый идентификатор дизайна может иметь несколько процессов, поэтому мы организуем эти два иерархически, и мы помещаем в другой поиск ha sh, где каждый регистр является ключом, а мы просто используем 1
в качестве ключа. Ключ не имеет значения.
Это дает нам другую структуру данных:
\ {
L83A {
55FIP {
70 1,
155 1
},
FRP {
141 1,
149 1,
151 1
}
},
L84A {
55FIP {
70 1,
155 1
}
}
}
Это намного легче понять и использовать позже.
Теперь мы анализируем пользователя ввод и итерации по каждой строке. Формат кажется понятным. Это немного похоже на файл CSV, но с использованием двоеточий :
, поэтому мы можем split
. Это дает нам два идентификатора, и все последующие значения являются регистрами, поэтому мы помещаем их в массив.
В вашем примере нет случая, когда идентификатор проекта не существует в файле XML, но учитывая, что это основано на пользовательском вводе, мы должны все равно проверить. В реальном мире данные всегда грязные.
Затем мы можем проверить, находится ли $process_id
exists
внутри $design_id
в наших данных. Если это не так, мы сообщаем пользователю и переходим к строке next
.
Затем мы должны выполнить итерацию всех идентификаторов регистра. Либо $register_id
существует в нашем втором поиске ha sh, либо его нет.
Это дает нам точный вывод, который вы ожидаете.
L84A: doesn't have FIP
L83A:
55FIP
70 - existing register ID
155 - existing register ID
15 - no existing register ID
Этот код намного короче, его легче читать и он работает быстрее. Я использовал Data :: Printer , чтобы показать структуры данных.