在 Perl 中如何计算字符串中的链式表达式?

发布于 2024-08-12 12:11:03 字数 284 浏览 1 评论 0原文

我不太确定如何称呼这些类型的表达式,所以一个例子会更容易...

Perl 中有没有一种方法可以计算像 a a a a a a a a b <= c?我有一个配置文件,允许用户为某些操作提供条件表达式。如果可能的话,我不想将条件分成两部分(就像我通常在代码中所做的那样),而是想以这种方式表示它。

I'm not really sure what to call these type of expressions, so an example would be easier...

Is there a way in Perl to evaluate expressions like a < b <= c? I have a configuration file that allows the user to provide conditional expressions for certain actions. Rather than splitting the condition into two parts (as I would normally do in code), I'd like to represent it this way, if possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

牵你的手,一向走下去 2024-08-19 12:11:03

Perl 6 中肯定会出现这种情况。但不幸的是,我不认为这是 Perl 5.10 借用的 Perl 6 的东西之一。

That's coming in Perl 6, for sure. But unfortunately, I don't think it's one of the things from Perl 6 borrowed by Perl 5.10.

梦中的蝴蝶 2024-08-19 12:11:03

这可读性稍差,但可以实现您想要的: a a a a a a a a a乙&& b <= c

This is slightly less readable, but accomplishes what you want: a < b && b <= c

刘备忘录 2024-08-19 12:11:03

正如其他人提到的,Perl5(还)没有链式比较。

但是,如果您正在从配置文件解析“a < b <= c”并且只想评估它,那么也许这可能是您的转向之后的结果?

use strict;
use warnings;
use 5.010;

my ($a, $b, $c) = (10, 20, 30);

say 'Its true!'  if comparison( $a, '<', $b, '<=', $c );

sub comparison {
    my $left = shift;

    while (my $cmp = shift) {
        my $right = shift;
        compare( $cmp, $left, $right ) or return;
        $left = $right;
    }

    return 1;
}

sub compare {
    my $op = shift;
    given ($op) {
        when ( '<'  ) { return $_[0] <  $_[1] }
        when ( '<=' ) { return $_[0] <= $_[1] }
        default       { die "Invalid comparison operator" }
    }
}

它只是一个基本的示例(即不完整且没有错误检查),但我认为您明白了。

您可能已经在 CPAN 上找到类似的内容。像 Parse::RPN 之类的东西可能是一个有用的建筑堵塞。

现在,如果您的问题是如何从字面上解析 a a a a a a a a a a < b <= c 那么那就又是一锅鱼了!

/I3az/

As others have mentioned Perl5 doesn't (yet) have chained comparisons.

However if you are parsing "a < b <= c" from a config file and just want to evaluate it then perhaps this maybe what your steering after?

use strict;
use warnings;
use 5.010;

my ($a, $b, $c) = (10, 20, 30);

say 'Its true!'  if comparison( $a, '<', $b, '<=', $c );

sub comparison {
    my $left = shift;

    while (my $cmp = shift) {
        my $right = shift;
        compare( $cmp, $left, $right ) or return;
        $left = $right;
    }

    return 1;
}

sub compare {
    my $op = shift;
    given ($op) {
        when ( '<'  ) { return $_[0] <  $_[1] }
        when ( '<=' ) { return $_[0] <= $_[1] }
        default       { die "Invalid comparison operator" }
    }
}

Its only a rudimentary example (ie. not complete and no error checking) but I think you get the idea.

And you may find something like this already on CPAN. Something like Parse::RPN maybe a useful building block.

Now if you question is about how to literally parse a < b <= c then that is another kettle of fish!

/I3az/

念﹏祤嫣 2024-08-19 12:11:03

暂时忽略任何输入验证或最终比较的执行,以下代码(或其较小的变体)应该能够重写您的语句:

sub rewrite {
    my $str = shift;
    my $ops = join "|" => qw/ < > <= >= == != /;
    1 while $str =~ s/ ($ops) \s* (\w+?) \s* ($ops) /$1 $2 && $2 $3/xg;
    $str
}

print rewrite "a < b < 5 < c != d";
# prints a < b && b < 5 && 5 < c && c != d

ignoring any input validation or execution of the eventual comparison for the moment, the following code (or a minor variation of it) should be able to rewrite your statement:

sub rewrite {
    my $str = shift;
    my $ops = join "|" => qw/ < > <= >= == != /;
    1 while $str =~ s/ ($ops) \s* (\w+?) \s* ($ops) /$1 $2 && $2 $3/xg;
    $str
}

print rewrite "a < b < 5 < c != d";
# prints a < b && b < 5 && 5 < c && c != d
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文