Perl регулярное выражение, означающее? Это ловит правильную вещь, XML в TXT - PullRequest
0 голосов
/ 26 июня 2019

Мне поручено попытаться обновить старый старый скрипт.Perl - не моя сильная сторона.Выходные данные указанного сценария представляют собой некоторую статистику, но я заметил, что в выходных строках он перемещает тег вниз к не тому устройству, я думаю, что это используется выражение регулярного выражения, что-то делает это, но я не могучтобы прочитать его.

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

  <ComputerStatus>
    <Name>PC1</Name>
    <VirusDefinitions>2019-06-23 rev. 001</VirusDefinitions>
    <LogonClient>Administrator</LogonClient>
    <IPAddress>192.168.2.2</IPAddress>
    <OperatingSystem>Windows Server 2008 R2 Standard Edition</OperatingSystem>
    <AutoProtectEnabled>1</AutoProtectEnabled>
    <AgentVersion>12.1.6168.6000</AgentVersion>
    <Status>1</Status>
    <LastUpdateTime>2019-06-25T09:53:19+12:00</LastUpdateTime>
    <Infected>0</Infected>
    <WorstInfectionIDX>9999</WorstInfectionIDX>
    <LastScanTime>2017-10-13T09:06:00+13:00</LastScanTime>
    <LastVirusTime>1970-01-01T00:00:00+13:00</LastVirusTime>
  </ComputerStatus>
  <ComputerStatus>
    <Name>PC2</Name>
    <VirusDefinitions>2019-06-23 rev. 001</VirusDefinitions>
    <LogonClient>Administrator</LogonClient>
    <IPAddress>192.168.2.3</IPAddress>
    <OperatingSystem>Windows Server 2012 R2 Standard Edition</OperatingSystem>
    <AutoProtectEnabled>1</AutoProtectEnabled>
    <AgentVersion>12.1.6168.6000</AgentVersion>
    <Status>1</Status>
    <LastUpdateTime>2019-06-25T09:54:59+12:00</LastUpdateTime>
    <Infected>0</Infected>
    <WorstInfectionIDX>9999</WorstInfectionIDX>
    <LastScanTime>2019-06-24T11:05:03+12:00</LastScanTime>
    <LastVirusTime>1970-01-01T00:00:00+13:00</LastVirusTime>
  </ComputerStatus>

Это XML-файл, из которого я анализирую статистику.Это еще не все.

my @NAMES = ("Name", "VirusDefinitions", "IPAddress", "OperatingSystem", "AgentVersion", "Infected", "LastScanTime","LastUpdateTime","WorstInfectionIDX","LastVirusTime","Threats","StartDateTime","StopDateTime","TotalFiles","Duration","AutoProtectEnabled" );
my $DEBUG = 2; # debug on = 1 low, = 2 detailed, = 3 full, = 0 OFF. Will print to screen needed in file the pipe >filename
my $DETAILED = 0; #
#vars
my $path = $ARGV[0];
my $TXT = $ARGV[1];
open( FIL, "< $FILEA" )|| die "cant open file $!" ;
while (defined ($_ = <FIL>)) {
foreach my $N (@NAMES) {
#print "looking for $N\n" ;
    if  ($_ =~ /$N/) {
    if ($DEBUG gt 2){print "report: Looking for $N\n";}
    $_ =~ /$N(.*)$N/;
    my $TMP = $1;
    $TMP =~ s/[\$#@~!&*()<>\[\];,?^ `\\\/]+//g;
    #Switch that has to be extended if the array NAMES is extended
        if ($N eq "Name") {
        $NAME=$TMP; 
        }elsif ($N eq "VirusDefinitions"){ 
        $VIRUSDEF=$TMP;
        }elsif ($N eq "IPAddress") {
        $IP=$TMP;
        }elsif ($N eq "OperatingSystem") {
        $OS=$TMP;
        }elsif ($N eq "AgentVersion") {
        $AGNT=$TMP;
        }elsif ($N eq "Infected") {
        $INFEC=$TMP;
        }elsif ($N eq "LastScanTime") {
        $LAST=$TMP;
        }elsif ($N eq "LastUpdateTime"){
        $LASTUP=$TMP;
        }elsif ($N eq "WorstInfectionIDX") {
        $winfid=$TMP;
        }elsif ($N eq "LastVirusTime") {
        $lastvirust=$TMP;
        }elsif ($N eq "Threats"){
        $threats=$TMP;
        }elsif ($N eq "StartDateTime"){
        $starttime=$TMP;
        }elsif ($N eq "StopDateTime"){
        $stoptime=$TMP;
        }elsif ($N eq "TotalFiles"){
        $totalfil=$TMP;
        }elsif ($N eq "Duration"){
        $scandur=$TMP;
        }elsif ($N eq "AutoProtectEnabled") {
        $autoprot=$TMP;
        $CUST =~ s/\W//g; #We shave special characters off of the $CUST variable and return normal characters
        print LOG "$today $time, <LastScan><$LAST><LastUpdateTime><$LASTUP><ProjectNr><$PROJNO><Site><$CUST><Device><$NAME><ThreatsFound><$threats><Definition><$VIRUSDEF><IpAddress><$IP><OS><$OS><AgentVersion><$AGNT><Infected><$INFEC><WorstInfectionID><$winfid><LastVirusDetectionTime><$lastvirust><ScanStartTime><$starttime><ScanStopTime><$stoptime><ScanDuration><$scandur><AutoProtectionEnabled><$autoprot><FilesScanned><$totalfil><FileName><$FILE1>\n" ;
        #init variables again
        init
        }       
    }else{
    #print "no match $N\n"
    }

Выше приведен кодовый бит, который анализирует файл xml и печатает его в текст.Мне известно, что код подвержен ошибкам.

$TMP =~ s/[\$#@~!&*()<>\[\];,?^ `\\\/]+//g;

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

190626 09:55:11, <LastScan><2019-06-19T22:36:04+02:00><LastUpdateTime><2019-06-20T20:58:17+02:00><ProjectNr><2><Site><redacted><Device><PC1><ThreatsFound><0><Definition><2019-06-23rev.001><IpAddress><192.168.2.2><OS><WindowsServer2008R2StandardEdition><AgentVersion><12.1.6168.6000><Infected><0><WorstInfectionID><9999><LastVirusDetectionTime><1970-01-01T00:00:00+01:00><ScanStartTime><2019-06-19T23:19:00+02:00><ScanStopTime><2019-06-19T23:25:35+02:00><ScanDuration><395><AutoProtectionEnabled><1><FilesScanned><130219><FileName><PerfMonSymantecEPM-20190625-AntiVirus.xml>
190626 09:55:11, <LastScan><2017-10-13T09:06:00+13:00><LastUpdateTime><2019-06-25T09:53:19+12:00><ProjectNr><2><Site><redacted><Device><PC2><ThreatsFound><0><Definition><2019-06-23rev.001><IpAddress><192.168.2.3><OS><WindowsServer2012R2StandardEdition><AgentVersion><12.1.6168.6000><Infected><0><WorstInfectionID><9999><LastVirusDetectionTime><1970-01-01T00:00:00+13:00><ScanStartTime><2019-06-19T23:19:00+02:00><ScanStopTime><2019-06-19T23:25:35+02:00><ScanDuration><395><AutoProtectionEnabled><1><FilesScanned><130219><FileName><PerfMonSymantecEPM-20190625-AntiVirus.xml>

Выше приведен текстовый выходной файл.Как видите, переменная «LastScan» печатается не на том устройстве.Я ослеп, уставившись на код и пытаясь выяснить, в чем заключается ошибка.

Я ни в коем случае не эксперт по Perl, я занимаюсь программированием в масштабе хобби в C #.Поэтому я надеюсь, что вы, эксперты, сможете мне помочь, я постарался сделать информацию максимально читабельной

1 Ответ

1 голос
/ 26 июня 2019

Это замена, которая обычно выглядит как

s/PATTERN/REPLACEMENT/

Модификатор /g означает «глобальный», то есть он заменяет все вхождения шаблона. Замена пуста, поэтому замена просто удаляет все совпадения шаблона.

s/[\$#@~!&*()<>\[\];,?^ `\\\/]+//g;
  ^                          ^^
  |                          |\
Beginning           End of the \
of a character   the character  One or more
class                   class   times

Шаблон соответствует любой последовательности символов $#@~!&*()<>[];,?^ `\/. Некоторые символы экранированы (им предшествует обратный слеш), чтобы предотвратить их интерпретацию как специальных символов.

Голый $ был бы интерпретирован как символ (начиная с имени переменной). [ не нужно убегать, но это не больно. ] был бы интерпретирован как конец класса символов. \ был бы интерпретирован как escape-символ, а / был бы интерпретирован как разделитель замены.

Использование регулярных выражений для обработки XML хрупко. В Perl есть несколько хороших библиотек разбора XML, которые следует использовать вместо этого (например, XML :: LibXML или XML :: Twig )

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...