【问题标题】:Run perl script within perl script using named arguments使用命名参数在 perl 脚本中运行 perl 脚本
【发布时间】:2018-09-18 09:06:16
【问题描述】:

我正在编写一个 Perl 程序,它必须在不同的输入上多次运行几个 Perl 脚本。

我尝试使用的脚本是 count.plstatistic.pl 来自 Text::NSP。 这些不是我自己写的,所以我不想尝试将它们重构为一个模块。

我看了 a similar question 并弄清楚如何使用system 方法 IPC::System::Simple.

但是,我想使用count.plstatistic.pl 中的命名参数。我还没有弄清楚如何做到这一点。这是我当前的代码:

system($^X, token="valid_tokens.txt", "/Users/cat/perl5/bin/statistic.pl", "ll.pm", "lab01_jav_bigrams.ll",
"/Users/cat/Perl_scripts/214_Final_project/lab01_java_bigrams.cnt");

这是我得到的错误:

在 ngram_calcs.PL 第 22 行,“valid_tokens.txt”附近,不能修改标量赋值中的常量项,在 ngram_calcs.PL 第 22 行使用“strict subs”时,不允许使用裸词“token”。

值得注意的是,在我添加命名参数之前,代码运行良好。如何为IPC::System::Simple 提供命名参数?还是有更好的方法来做我想做的事情?

编辑:谢谢,Haukex,我确实有错误的参数,并且使用“--token=valid_tokens.txt”有效。

即使问题解决了,我也会分享更多背景信息,以便其他看到的人受益。在命令行上我会输入:

count.pl -token validtokens.txt lab01_java_bigrams.cnt Users/cat/CS214/lab01_java.txt
statistic.pl -score 6.63 ll.pm lab01_java.ll lab01_java_bigrams.cnt

这是正确的 perl 代码:

system($^X, "/Users/cat/perl5/bin/count.pl", "--token=valid_tokens.txt", "lab01_java_bigrams.cnt", $filename);
system($^X, "/Users/cat/perl5/bin/statistic.pl", "--score=6.63", "ll.pm", "lab01_java_bigrams.ll", "/Users/cat/Perl_scripts/214_Final_project/lab01_java_bigrams.cnt");

【问题讨论】:

  • 什么是token="valid_tokens.txt"?我不希望这是对“命名参数”的有效使用。您如何从命令行调用该程序?您只能以编写为接受它们的方式将参数传递给程序。至于您显示的错误,“ngram_calcs.PL”中的相关代码是什么(如果需要简化)?
  • 您不是“向 IPC::System::Simple 提供命名参数”。该模块提供了替换 system 内置命令并为该程序提供给它们的命令。
  • 我建议您编辑问题并展示这些程序是如何从命令行自行调用的,而无需您正在编写的脚本。您还想显示您正在编写的脚本的代码。

标签: perl ipc


【解决方案1】:

假设您对statistic.pl 的调用基本正确,system 的参数需要如下所示

system($^X,
    "/Users/cat/perl5/bin/statistic.pl",
    qq/token="valid_tokens.txt"/,
    "ll.pm",
    "lab01_jav_bigrams.ll",
    "/Users/cat/Perl_scripts/214_Final_project/lab01_java_bigrams.cnt"
);

即所有参数都属于程序文件之后,并且整个命名参数字符串必须用引号引起来

请阅读下面 haukex 的评论以了解另一个潜在错误

【讨论】:

  • 脚本的参数需要在脚本之后,而不是在perl之后。此外,as far as I can telltoken 需要两个破折号,并且在参数中包含引号会导致目标脚本尝试打开文件名包括这些引号。
【解决方案2】:

我对您的 system 调用感到困惑。查看statistic.plcount.pl 的来源,似乎只有后者采用token 参数,但您似乎没有运行count.pl$^X 是当前运行的 Perl 解释器,它通常后面跟 interpreter 的任何参数,然后是脚本的名称,然后是 脚本的任何参数,所以将token 参数放在脚本之前对我来说没有意义。

例如,如果您尝试将count.pl 的输出通过管道传输到statistic.pl,则必须进一步解释,因为这是IPC::System::Simple 无法处理的(至少在不调用shell 的情况下) ,我不建议这样做),并且您需要更高级的模块,例如IPC::Run。现在,我假设您想将 token 参数传递给支持它的脚本。

命令行参数只是字符串。如果您要从 *NIX shell 编写类似./script.pl token="test file" foo bar 的内容,那么 shell 将接管对空格和引用的解释。 script.pl 将得到一个字符串列表,如 ("token=test file", "foo", "bar")(注意 shell 如何处理那里的引号)。

这个字符串列表是您需要传递给system 的内容,它不一定与您在命令行上键入的内容相同。由被调用程序来解释这些参数。您正在运行的两个脚本使用Getopt::Long,并且命名参数需要以两个破折号作为前缀。所以这样的事情应该可以工作:

system($^X, "/Users/cat/perl5/bin/count.pl", "--token=valid_tokens.txt", ...);

关于如何传递包含引号等特殊字符的参数(在这种情况下不适用),Perl 中有多种语法:"--foo=\"bar\""'--foo="bar"'q{--foo="bar"}(参见Quote and Quote-like Operators) .

【讨论】:

    【解决方案3】:

    你可以试试这个格式吗?

    system('/Users/cat/perl5/bin/statistic.pl  --token valid_tokens.txt  ll.pm  lab01_jav_bigrams.ll  /Users/cat/Perl_scripts/214_Final_project/lab01_java_bigrams.cnt');
    

    但我检查了 CPAN 模块的来源,似乎 tokencount.pl 的选项,但不是 statistic.pl

    无论如何,任何选项都可以指定类似于--token valid_tokens.txt

    希望对您有所帮助!

    【讨论】:

    • system 带有单个字符串参数的缺点是它可能会导致命令通过默认 shell 传递,从而导致 shell 元字符产生影响。除非特别需要这些插值,否则system 的多参数形式更安全。
    猜你喜欢
    • 2015-03-15
    • 2010-09-26
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 2012-08-29
    • 2013-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多