Как я могу “сохранить” оператор в переменной в Perl?

Я ищу способ сделать это в Perl:

$a = "60"; $b = "< 80";

if ( $a $b ) {  then .... }

Здесь, $b "содержит" оператор... я могу сделать это? Возможно, некоторый другой путь?

8
задан P Shved 21 March 2010 в 00:07
поделиться

5 ответов

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

подробнее см. perldoc eval

7
ответ дан 3 November 2019 в 12:27
поделиться

Приятно видеть, как люди открывают для себя функциональное программирование. : -)

К счастью, Perl имеет возможность создавать и сохранять функции на лету. Например, образец в вашем вопросе будет выглядеть так:

$a = "60"; $b = sub { $_[0] < 80 };

if ( $b->($a) ) { .... }

В этом примере ссылка на анонимную подпрограмму хранится в $ b , подпрограмма имеет тот же синтаксис для передачи аргументов, что и обычно. один. -> затем используется для вызова по ссылке (тот же синтаксис, который вы, вероятно, используете для ссылок на массивы и хэши).

Но, конечно, если вы хотите просто построить выражения Perl из произвольных строк, вы можете использовать eval :

$a = "60"; $b = " < 80";

if ( eval ("$a $b") ) { .... }

Однако делать это через eval нельзя. безопасно, если строка, которую вы оцениваете, содержит части, которые вводятся пользователем. Синан Унур прекрасно объяснил это в своем комментарии-ответе .

18
ответ дан 3 November 2019 в 12:27
поделиться

Как насчет определения функции, которая обертывает необходимое условие:

my $cond = sub { $_[0] < 80 };

if ( $cond->( $a ) ) { 
     ...
}
8
ответ дан 3 November 2019 в 12:27
поделиться

Это должен быть комментарий, но комментарии слишком тесны для чего-то вроде этого, поэтому я делаю его 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 и $ b в качестве имен переменных, поскольку это волшебные локальные переменные пакета, используемые sort , и поэтому они освобождены от strict - и вы должны всегда использовать strict и предупреждения в своих программах.

8
ответ дан 3 November 2019 в 12:27
поделиться

Интересно, представляет ли здесь интерес Number::Compare? Из примера:

 Number::Compare->new(">1Ki")->test(1025); # is 1025 > 1024

 my $c = Number::Compare->new(">1M");
 $c->(1_200_000);                          # slightly terser invocation
1
ответ дан 3 November 2019 в 12:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: