代码之家  ›  专栏  ›  技术社区  ›  Ricky Levi

如何在Perl中的变量中“存储”运算符?

  •  7
  • Ricky Levi  · 技术社区  · 16 年前

    我正在寻找一种在Perl中实现这一点的方法:

    $a = "60"; $b = "< 80";
    
    if ( $a $b ) {  then .... }
    

    在这里, $b “保留”操作员…我能做这个吗?也许是别的办法?

    6 回复  |  直到 8 年前
        1
  •  6
  •   ghostdog74    16 年前
    $a = "60"; $b = "< 80";
    if( eval($a. $b)){
      print "ok";
    }
    

    看见 perldoc eval 为了更多

        2
  •  18
  •   Community Mohan Dere    9 年前

    很高兴看到人们如何发现函数式编程。-)

    幸运的是,Perl能够动态地创建和存储函数。例如,问题中的示例如下所示:

    $a = "60"; $b = sub { $_[0] < 80 };
    
    if ( $b->($a) ) { .... }
    

    在本例中,对匿名子例程的引用存储在 $b 子程序的参数传递语法与通常的相同。 -> 然后用于按引用调用(与对数组和哈希的引用可能使用的语法相同)。

    但是,当然,如果您只想从任意字符串构造Perl表达式,那么可能需要使用 eval :

    $a = "60"; $b = " < 80";
    
    if ( eval ("$a $b") ) { .... }
    

    但是,通过 埃瓦 如果要评估的字符串包含作为用户输入的部分,则不安全。 Sinan Ünür explained it perfectly in his answer-comment .

        3
  •  8
  •   friedo    16 年前

    如何定义一个包装所需条件的函数:

    my $cond = sub { $_[0] < 80 };
    
    if ( $cond->( $a ) ) { 
         ...
    }
    
        4
  •  8
  •   Sinan Ünür    16 年前

    这应该是一个评论,但评论太过狭隘,不适合这样的事情,所以我把它变成了CW。

    对于您显示要传递到的变量内容的位置的情况 string eval ,接受的解决方案是正确的。

    但是,如果 $a 和 $b 来自用户输入,然后查看以下脚本:

    #!/usr/bin/perl
    
    use strict; use warnings;
    
    my $x = '80';
    my $y = '; warn "evil laugh!\n"; exit';
    
    if ( eval ($x . $y) ) {
        print "it worked!!!\n";
    }
    

    如果字符串是由用户输入的,则没有任何内容阻止用户将字符串传递给您的程序。 ';system "rm -rf /bin"' .

    因此,正确的问题解决方案需要编写或使用表达式解析器。

    顺便说一句,你不应该使用 $A 和 美元 作为变量名作为神奇的包本地变量 sort 因此,他们可以免于 strict -你呢? 必须 总是使用 严格的 和 warnings 在你的程序中。

        5
  •  1
  •   Sinan Ünür    16 年前

    我不知道是否 Number::Compare 对这里有任何兴趣。从示例中:

     Number::Compare->new(">1Ki")->test(1025); # is 1025 > 1024
    
     my $c = Number::Compare->new(">1M");
     $c->(1_200_000);                          # slightly terser invocation
    
        6
  •  0
  •   Nathan Neulinger    8 年前

    如果您信任(或能够充分验证)$op并且不信任输入的安全性,则表单更安全:

    my $compare_x = $user_input_x;
    my $compare_y = $user_input_y;
    my $op = <some safe non-user-input, or otherwise checked against a safe list>;
    if ( eval("\$compare_x $op \$compare_y") )
    {
     ...
    }