2015-02-23 1 views
1

Я новичок в Perl и пытаюсь применить условие фильтра к файлам XML с помощью модуля XML::Twig.Как применить предложение IN в Perl, передав аргументы из командной строки

Ниже мой код:

#!/usr/bin/perl 
use strict; 
use warnings; 

use XML::Twig; 

my $SOURCEFILE  = $ARGV[0]; 
my $FILELOCATIONIN = $ARGV[1]; 

my $twig = new XML::Twig(twig_handlers => { 'STOCKEXT/STOCK' => \&STOCK }); 

$twig->parsefile($FILELOCATIONIN.'/'.$SOURCEFILE.'.xml'); 

$twig->set_pretty_print('indented'); 

$twig->print_to_file($FILELOCATIONIN.'/'.$SOURCEFILE.'out.xml'); 

sub TRADE { 
    my ($twig, $STOCK) = @_; 
    foreach my $c ($STOCK) 
     { 
     $c->delete($STOCK) 
     unless 
     $c->att('origin') eq "HIGH_TRADE" 

     ; 
    } 
} 

Ниже мой XML:

<STOCKEXT> 
    <STOCK origin = "HIGH_TRADE"/> 
    <STOCK origin = "HIGH_TRADE"/> 
    <STOCK origin = "HIGH_TRADE"/> 
    <STOCK origin = "LOW_TRADE"/> 
    <STOCK origin = "LOW_TRADE"/> 
    <STOCK origin = "AVERAGE_TRADE"/> 
</STOCKEXT> 

Отфильтрованный Выходной XML:

<STOCKEXT> 
    <STOCK origin = "HIGH_TRADE"/> 
    <STOCK origin = "HIGH_TRADE"/> 
    <STOCK origin = "HIGH_TRADE"/> 
</STOCKEXT> 

Теперь я застрял, как я хочу передать запятой -раздельный аргумент в командной строке, так что HIGH_TRADE, а также AVERAGE_TRADE станут legi timate STOCK.

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

Поэтому я ожидаю мой код, который будет использоваться в качестве

perl stock_filter.pl file_name.xml /opt/XML HIGH_TRADE,AVERAGE_TRADE 

Третий аргумент будет расколоть и сверяется атрибута каждого элемента STOCKorigin объявить его законным.

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

ответ

2

Один из способов сделать это - сохранить значения, которые вы хотите сохранить в хеше.

Создать хэш в верхней части сценария:

my @origins_to_keep= split /,/, $ARGV[2]; 
my %keep= map { $_ => 1 } @origins_to_keep; 

Используйте его в обработчике:

$c->delete($STOCK) unless $keep{$c->att('origin')} 
+0

Глобальный символ "% Keep" требует явного пакета name..error это метание ... Не понимаю, почему .. –

+0

Понял ... вместо того, чтобы мой $ keep = map {$ _ => 1} origins_to_keep, это должен быть мой% keep = map {$ _ => 1} @origins_to_keep, так как он hash ... спасибо ... –

+1

oops, исправлено в ответе – mirod

3

решение наиболее очевидным для меня, чтобы использовать функцию any из List::Util модуля ,

Вот версия вашего собственного кода, которая включает в себя несколько других модификаций. Самое важное, что я использовал функцию catfile от модуля File::Spec::Functions, чтобы более безопасно комбинировать путь и имя файла.

use strict; 
use warnings; 
use 5.014; # For non-destructive substitution 

use XML::Twig; 
use File::Spec::Functions 'catfile'; 
use List::Util 'any'; 

my ($source_file, $file_location, $stock_origins) = @ARGV; 

my $twig = XML::Twig->new(
    twig_handlers => { 'STOCKEXT/STOCK' => \&stock_handler }, 
    pretty_print => 'indented', 
); 

my $full_input = catfile($file_location, $source_file); 
my @stock_origins = split /,/, $stock_origins; 
my $full_output = $full_input =~ s/(?=\.[^.]+\z)/_out/r; 

$twig->parsefile($full_input); 
$twig->print_to_file($full_output); 

sub stock_handler { 
    my ($twig, $stock) = @_; 
    my $origin = $stock->att('origin'); 

    $stock->delete unless any { $origin eq $_ } @stock_origins; 
} 

выход

<STOCKEXT> 
    <STOCK origin="HIGH_TRADE"/> 
    <STOCK origin="HIGH_TRADE"/> 
    <STOCK origin="HIGH_TRADE"/> 
    <STOCK origin="AVERAGE_TRADE"/> 
</STOCKEXT> 
+0

"any "не экспортируется модулем List :: Util .... Это ошибка, с которой я столкнулся ... Любая идея ... Сэр .. –

+0

Вам необходимо обновить свою копию' List :: Util' – Borodin

+1

Yeeah получил это !!!!!! –