【问题标题】:perl: use string as piece of codeperl:使用字符串作为一段代码
【发布时间】:2010-07-31 09:21:50
【问题描述】:

我想在我的 perl 程序中使用一个字符串(例如从文件中读取)作为一段代码。例如,我读取了一个字符串(例如$str="1..100,171,398..1000"),然后我想打印该字符串表示的范围内的所有数字。

谢谢, 戴夫

【问题讨论】:

  • 你到底是什么意思?您的文本看起来像是您想要读取字符串并将其作为 Perl 语句执行,但您的示例似乎是您想要将字符串解析为一些代码的输入的情况。是哪个?
  • 我想读入一个字符串并将其作为 Perl 语句执行。例如,我可以使用for $i (1..100,171,398..1000) {print "$i "} 来实现我的目标。

标签: perl string


【解决方案1】:

具体情况见How can I expand a string like "1..15,16" into a list of numbers?

一般情况下,eval 用于执行字符串中的代码。如果您要执行整个代码文件,请使用do。但在考虑这一点之前,请确保文件/字符串是安全的。 如果实际上“代码”仅限于您的示例,请使用 eval 或执行。

更新:事实证明 Number::Range 对于大范围来说很慢;对于您的情况,您最好在范围内使用 - 而不是 .. 并使用 Set::IntSpan。您询问效率:使用数组将消耗几兆字节的内存,但这并不是那么糟糕。 Set::IntSpan 确实提供了您可以使用的迭代方法,而不仅仅是生成数组,但我可能不会打扰。

【讨论】:

  • 感谢 Number::Range!添加另一个问题:我的范围非常大(约 50 万个数字,通常只有两个块,即 1..20000,,700000..1000000)。将它们简单地打印到文件中的最有效方法是什么?创建一个实际的数组(如示例中所示)似乎不是一个好主意,或者是吗?
【解决方案2】:

Number::Range 使用您拥有的 .. 语法,但它没有迭代器。 Set::IntSpan 使用 - 而不是 ..,但它确实有一个迭代器,这使得打印出集合而无需创建巨大的数组。

use Set::IntSpan;

my $str = "1..100,171,398..1000";
$str =~ s/\.\./-/g;
my $set = Set::IntSpan->new($str);

for (my $i = $set->first; defined $i; $i = $set->next) {
  print "$i\n"; # Or however you'd like to format it
}

在内部,Set::IntSpan 存储范围,所以这应该是相当节省内存的。您还可以使用spans 方法来获取解析的范围。这将需要您编写更多代码,但这意味着您不必对范围内的每个数字进行方法调用。 Perl 中的方法调用有点慢,但我不会担心,除非上面的代码运行时间太长。

【讨论】:

  • 谢谢 cjm。一个不错且优雅的解决方案,但它对我不起作用,因为 Set::IntSpan 需要对范围进行排序,而我的不一定(出于某种原因)。
【解决方案3】:

您可以使用 eval 在变量中执行代码。虽然插值可以很有趣。

eval "for ($str) { print \"\$_\n\";}"

【讨论】:

    猜你喜欢
    • 2013-06-22
    • 2021-12-03
    • 2010-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多