【问题标题】:Perl : string of variable within a variablePerl:变量中的变量字符串
【发布时间】:2017-06-21 15:05:30
【问题描述】:

这是我正在尝试做的一个示例: 我想为输入“定义”一个名称,然后当它被带入一个函数时,它才会替换所有 3 个变量。

$place_holder = 'f${file_case}_lalal_${subcase}_${test}';

....另一个函数中的其他地方:

读取文件,每行包含 3 组数字,代表 $file_case、$subcase、$test

while(<IN>){
   ($file_case, $subcase, $tset) = split;
   $input = $place_holder    #### line #3 here needs to fix
   print " $input \n";
}

不幸的是,它会为每一行打印出 f${file_case}lalal${subcase}_${test}。我希望这些变量被替换。我该怎么做,怎么做 我是否更改第 3 行以便能够按我的意愿输出?我不想在子程序中定义输入名称,它必须在主程序中。

【问题讨论】:

  • 注意:插值只发生在双引号字符串中,但您的示例是单引号。
  • 我知道。 $place_holder 当时的作用就像一个函数,这 3 个变量还不知道。因此不能被替代。但是 $place_holder 需要放在一个用户可以轻松更改为他们喜欢的地方的地方。其余的替换隐藏在用户不需要更改的函数中。

标签: string perl variables


【解决方案1】:

例如,如果满足您的条件,您可以使用子例程来做到这一点

use warnings;
use strict;

my $place_holder = sub {
    my ($file_case, $subcase, $test) = @_;    
    return "f${file_case}_lalal_${subcase}_${test}";
}

# ...

while (<IN>) { 
    my ($file_case, $subcase, $tset) = split;
    #
    #  Code to validate input
    #
    my $input = $place_holder->($file_case, $subcase, $tset);
    print "$input\n";
}

我已经使用了code reference 和anonymous subroutine 以期待可能从中受益的用途,但是对于指定的任务,您也可以使用普通的子例程。

注意你有$test和$tset,不影响上面的,但可能是错别字。

【讨论】:

  • 谢谢。这当然是让它优雅工作的一种方法。
  • @OngBengSeong 谢谢——我想到的要点是它分离了处理阶段以便于管理(例如,精确的变量名无关紧要),coderef 可以传递为需要——它避免了eval-ing 用户输入。
  • 如果我有 12 组不同的文件名并且我使用子程序样式 my $file_name = sub{ }
  • @OngBengSeong 你的意思是整个事情处理一个文件,它需要为 12 个不同的文件完成?您只需将它们全部放在这些文件名上的循环中。因此,对于每个文件名,都定义了 my $place_holder = sub { ... };(然后打开文件),然后您从其中读取文件名,执行 while (&lt;IN&gt;) 中的内容。如果涉及更多内容,则可能是一个很好的单独问题
  • 您好 Zdim,您会很高兴知道我知道最终会像您的建议一样为名称使用子例程。实际上我都试过了,几天后,换成我认为更优雅和更有条理的子程序版本。再次感谢您!
【解决方案2】:

试试 eval while(&lt;IN&gt;){ ($file_case, $subcase, $tset) = split; $input = eval $place_holder #### line #3 here needs to fix print " $input \n"; }

【讨论】:

  • 不幸的是,我之前尝试过,但它不起作用。谢谢。
  • 你遇到了什么错误?如果您没有选择它,它与您的解决方案相同。所以它应该可以工作。
【解决方案3】:

在我发布了一段时间后,我找到了一种方法。

在 ## 第 3 行,执行以下操作:

($input = $place_holder) =~ s/(\${w+})/$1/eeg;

一切正常。是的,上面的 tset 是一个错字,是为了测试。感谢大家的回复。

【讨论】:

  • 这是我最初警告过的——它评估用户输入。这本质上是危险的。我的意思不仅仅是可能的恶意,而是可能会评估仅仅拼写错误或错误的数据,从而对您的代码造成严重破坏。请注意,此eval-uates 将$1 的内容作为任意Perl 代码。 (这就是为什么我没有在回答中提到它,尽管在早期的评论中提到了它。)如果有其他方法,我强烈建议不要这样做。
  • 我之前的评论中的“用户输入”,我的意思也是从数据输入。我们永远无法确定“数据”文件中的内容。我要补充一条评论,在/ee之前需要对数据进行广泛验证,这涉及到eval。
  • 很高兴您自己找到了一个可行的解决方案并将其发布(顺便说一句,我没有投反对票)。
【解决方案4】:

您可以像这样使用String::Interpolate 模块

use String::Interpolate 'interpolate';

my $place_holder = 'f${file_case}_lalal_${subcase}_${test}';


while ( <IN> ) {
    my ($file_case, $subcase, $test) = split;

    my $input = interpolate($place_holder);
    print "$input\n";
}

该模块可以访问执行双引号内插的 Perl 内置 C 代码,因此通常快速且准确

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-07
    • 2012-03-28
    • 2017-01-17
    相关资源
    最近更新 更多