如何通过从命令行传递参数在 Perl 中应用 IN 子句
How to apply an IN clause in Perl by passing arguments from the command line
我是 Perl 新手,正在尝试使用 XML::Twig
模块对 XML 文件应用过滤条件。
以下是我的代码:
#!/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
成为合法的 STOCK
.
可以看出,在我当前的代码中,我传递了两个参数。但是我想传递三个参数,第三个应该是逗号分隔格式的过滤条件。
因此,我希望我的代码被调用为
perl stock_filter.pl file_name.xml /opt/XML HIGH_TRADE,AVERAGE_TRADE
第三个参数将被拆分并根据每个 STOCK
元素的 origin
属性进行检查以声明它是合法的。
这将有助于将来更改过滤条件。任何过滤条件的增减都不会改变代码。
实现此目的的一种方法是将要保留的值存储在散列中。
在脚本顶部创建哈希:
my @origins_to_keep= split /,/, $ARGV[2];
my %keep= map { $_ => 1 } @origins_to_keep;
在处理程序中使用它:
$c->delete($STOCK) unless $keep{$c->att('origin')}
对我来说最明显的解决方案是使用 List::Util
模块中的 any
函数。
这是您自己的代码版本,其中包含一些其他修改。最重要的是,我使用了 File::Spec::Functions
模块中的 catfile
函数来更安全地组合路径和文件名。
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>
我是 Perl 新手,正在尝试使用 XML::Twig
模块对 XML 文件应用过滤条件。
以下是我的代码:
#!/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
成为合法的 STOCK
.
可以看出,在我当前的代码中,我传递了两个参数。但是我想传递三个参数,第三个应该是逗号分隔格式的过滤条件。
因此,我希望我的代码被调用为
perl stock_filter.pl file_name.xml /opt/XML HIGH_TRADE,AVERAGE_TRADE
第三个参数将被拆分并根据每个 STOCK
元素的 origin
属性进行检查以声明它是合法的。
这将有助于将来更改过滤条件。任何过滤条件的增减都不会改变代码。
实现此目的的一种方法是将要保留的值存储在散列中。
在脚本顶部创建哈希:
my @origins_to_keep= split /,/, $ARGV[2];
my %keep= map { $_ => 1 } @origins_to_keep;
在处理程序中使用它:
$c->delete($STOCK) unless $keep{$c->att('origin')}
对我来说最明显的解决方案是使用 List::Util
模块中的 any
函数。
这是您自己的代码版本,其中包含一些其他修改。最重要的是,我使用了 File::Spec::Functions
模块中的 catfile
函数来更安全地组合路径和文件名。
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>