【问题标题】:Perl pass arguments into file from BashPerl 将参数从 Bash 传递到文件中
【发布时间】:2017-12-05 15:18:17
【问题描述】:

我必须在 Perl 文件中运行一个函数,并将参数传递给该函数。

# program.pm

sub go
{
   # I need to use arguments here
   # print foo
   # print bar
}

my %functions = (
  go  => \&go
);

my $function = shift;

if (exists $functions{$function}) {
  $functions{$function}->();
} else {
  die "There is no function called $function available\n";
}

这需要通过 bash 运行和传递。我需要能够随机指定参数,如下所示:

$ perl program.pm go foo='bar' bar='fubar'

我对 Perl 很陌生。我在谷歌上搜索,无法为我的生活弄清楚如何正确解析这些。似乎有 4 种不同的方法可以做到这一点,但似乎没有一个适合我的用例。

我也试过了,没用。:

$ perl program.pm -e 'go(foo=>"bar")'

【问题讨论】:

标签: bash perl arguments


【解决方案1】:

您已经接受的答案似乎相当复杂。只需对现有代码进行几处更改,就可以做到这一点。

sub go
{
   # I need to use arguments here
   # print foo
   # print bar
   print "In go\nArgs are: @_\n";
}

my %functions = (
  go  => \&go
);

my $function = shift;

if (exists $functions{$function}) {
  # Pass remaining command-line args to the called subroutine
  $functions{$function}->(@ARGV);
} else {
  die "There is no function called $function available\n";
}

我已经在go() 中调用了print()(所以我知道它正在被调用),并且我已经将@ARGV 传递给了调度表中的子例程。

您可以像任何其他 Perl 程序一样调用它。

$ perl program.pm go foo=bar bar=fubar
In go
Args are: foo=bar bar=fubar

$ perl program.pm XX foo bar
There is no function called XX available

更新:在评论中,添加了此要求:

但是如何将值拆分为哈希?

对此有两个答案。而你选择哪一个取决于你实际想要做什么。

如果您只想获取任何“foo=bar”字符串并将其解析为存储在哈希中的键/值对,则可以将go() 子例程替换为如下代码:

use Data::Dumper;

sub go
{
   # I need to use arguments here
   # print foo
   # print bar

   my %args = map { split /=/ } @_;

   print "In go\nArgs are: " . Dumper(\%args) . "\n";
}

然后你会得到这个输出:

$ perl program.pm go foo=bar bar=fubar
In go
Args are: $VAR1 = {
          'bar' => 'fubar',
          'foo' => 'bar'
        };

如果您实际上是在尝试解析命令行选项,那么您应该使用像 GetOpt::Long 这样的命令行选项解析器。

use Data::Dumper;
use Getopt::Long 'GetOptionsFromArray';

sub go
{
   # I need to use arguments here
   # print foo
   # print bar

   my %args;

   GetOptionsFromArray(\@_, \%args, 'foo=s', 'bar=s');

   print "In go\nArgs are: " . Dumper(\%args) . "\n";
}

请注意,要使其正常工作,您需要传递以 -- 开头的正确 Unix 样式选项。

$ perl program.pm go --foo=bar --bar=fubar
In go
Args are: $VAR1 = {
          'bar' => 'fubar',
          'foo' => 'bar'
        };

但这个版本的输入要求要灵活得多:

$ perl program.pm go --f bar --b fubar
In go
Args are: $VAR1 = {
          'bar' => 'fubar',
          'foo' => 'bar'
        };

它会告诉你是否使用了无效的选项名称。

$ perl program.pm go --fu=bar --baz=fubar
Unknown option: fu
Unknown option: baz
In go
Args are: $VAR1 = {};

【讨论】:

  • 但是如何将值拆分为哈希?
  • 哦。对于没有发现您在问题中没有提到的要求,我深表歉意:-)
  • 哈哈对不起!我确实更喜欢你的方式,如果有一些容易解析它们的话。
【解决方案2】:

您可以使用 require 将 program.pm “包含”到您的“单行”中。

shell/bash 脚本

perl -e 'require "/path/program.pm" ; &go(1=>2)'

程序.pm

sub go
{
   # sample subroutine

   # print subroutine parameters
   print "go-params: @_\n";
   # convert subroutine parameters into hash
   my %hash = @_;
   print "go-hash-1: $hash{1}\n"
}
# IMPORTANT: indicate proper module initialization
1;

【讨论】:

  • 你为什么require这个程序而不是仅仅运行它?而子程序调用上的&又是什么作用呢?
  • @DaveCross 1) Require 应该使 program.pl 中定义的 许多子例程 在“一个班轮”中可用。 2) & 在这种情况下不需要调用go 子程序。这是我首选的风格指南。 3)你的回答是“更好和推荐的风格”。我的回答是“短代码”,并且可以更复杂地使用 program.pm 中定义的子路由
  • 1/ 但是如果你只是运行程序,无论如何都会定义子程序。 2/ 使用& 很少需要调用子程序。如果这是您的首选方法,那么您编写的代码比需要的更难阅读。
  • @DaveCross 1) 展示你从文件和一个衬里集成子例程的方式 (-e 2) “它更难阅读” - 这是个人喜好问题,可能是“不合适”的解释其他语言的习惯。它使代码更易于阅读对我来说
  • 1/ 没有可显示的内容。它只是工作。如果你从命令行运行一个程序,那么它的所有子程序都对你可用。 2/ & 不仅仅是个人喜好问题。 & 可以改变子例程以模糊方式调用的方式。除非您了解foo&foo 之间的区别,否则我强烈建议您不要使用后者。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-20
  • 2015-06-27
  • 1970-01-01
相关资源
最近更新 更多