以函数式解析嵌套/相关值字符串

发布于 2024-09-24 20:16:04 字数 1064 浏览 2 评论 0原文

$tasks->{t1}{cmdline} = "convert -f %FONT% %1%";
$tasks->{t1}{report} = "Launched as %CMD% by %USER%";
$tid = 't1';
foreach my $parm (keys %{$tasks->{$tid}}) {
    $tasks->{$tid}{$parm}=~s/%FONT%/$tasks->{$tid}{font}/g; # may evaluate if $parm == 'cmdline';
    $tasks->{$tid}{$parm}=~s/%CMD%/$tasks->{$tid}{cmdline}/g;
}

该代码很糟糕,因为它需要在 foreach 之外进行另一个循环(以确保替换所有复制的值),并且还包含太多文本数据。目前重写的最佳方法如下所示:

foreach my $parm (keys %{$tasks->{$tid}}) {
 &lookupValues(\$tasks->{$tid}{&parm}); # or ($parm) if strict refs?
}

但是它仍然需要对键进行排序以便检测优先级(如果在 %FONT% 之前替换 %CMD%,则 $tasks->{$tid}{report} 是错误的)。

foreach my $parm ( &SORTME($tasks->{$tid}) ) {&lookupValuesFor($tid,$parm); }

根据指定变量的数量及其关系进行排序的最佳方法是什么?原生的(大量循环和哈希),或expat [相关问题以某种方式将我指向expat,也会调查它:解析嵌套模式的字符串]或其他解析器?

现在不喜欢 $object->value('cmdline') 的 OOP 方式。

$tasks->{t1}{cmdline} = "convert -f %FONT% %1%";
$tasks->{t1}{report} = "Launched as %CMD% by %USER%";
$tid = 't1';
foreach my $parm (keys %{$tasks->{$tid}}) {
    $tasks->{$tid}{$parm}=~s/%FONT%/$tasks->{$tid}{font}/g; # may evaluate if $parm == 'cmdline';
    $tasks->{$tid}{$parm}=~s/%CMD%/$tasks->{$tid}{cmdline}/g;
}

The code is bad, because it needs another loop outside foreach (to ensure that all copied values were replaced), and also contains too much textual data. The best way to rewrite currently looks as:

foreach my $parm (keys %{$tasks->{$tid}}) {
 &lookupValues(\$tasks->{$tid}{&parm}); # or ($parm) if strict refs?
}

However it still needs to have keys sorted in order to detect priority (if %CMD% is replaced before %FONT%, $tasks->{$tid}{report} is wrong).

foreach my $parm ( &SORTME($tasks->{$tid}) ) {&lookupValuesFor($tid,$parm); }

What is a best way to sort depending on the number of specified variables and their relations? Native one (lots of loops and hashes), or expat [ Related questions are somehow pointing me to expat, would investigate it too: Parsing a string for nested patterns ] or other parser?

OOP way of $object->value('cmdline') is not liked now.

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

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

发布评论

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

评论(1

錯遇了你 2024-10-01 20:16:04

这段代码“有效” - 并且对我来说看起来更干净。它是否能达到你想要的效果更有争议。

use strict;
use warnings;

my $tasks;

# Demonstration setup
$tasks->{t1}{cmdline} = "convert -f %FONT% %1%";
$tasks->{t1}{report}  = "Launched as %CMD% by %USER%";
$tasks->{t1}{maps} = {
    '%USER%'    => 'user-expansion',
    '%1%'       => 'one-expansion',
    '%FONT%'    => 'font-expansion',
    '%CMD%'     => 'cmd-expansion',
};

# Do the substitutions
foreach my $tid (keys %$tasks)
{
    my $task = $tasks->{$tid};
    my $maps = $task->{maps};
    foreach my $map (keys %$maps)
    {
        foreach my $key (keys %{$task})
        {
            next if ref $task->{$key};
            $task->{$key} =~ s/$map/$maps->{$map}/g;
        }
    }
}

# Demonstration printing
foreach my $tid (keys %$tasks)
{
    my $task = $tasks->{$tid};
    foreach my $key (keys %{$task})
    {
        next if ref $task->{$key};
        printf "%s: %-8s = %s\n", $tid, "$key:", $task->{$key};
    }
}

在 MacOS X (10.6.4) 上使用 Perl 5.13.4 的输出是:

t1: report:  = Launched as cmd-expansion by user-expansion
t1: cmdline: = convert -f font-expansion one-expansion

三重循环几乎是不可避免的;您希望将每个映射应用于每个任务的每个字符串。一般来说,每个任务都可以有自己的映射。

This code 'works' - and looks cleaner to me. Whether it does what you're after is more debatable.

use strict;
use warnings;

my $tasks;

# Demonstration setup
$tasks->{t1}{cmdline} = "convert -f %FONT% %1%";
$tasks->{t1}{report}  = "Launched as %CMD% by %USER%";
$tasks->{t1}{maps} = {
    '%USER%'    => 'user-expansion',
    '%1%'       => 'one-expansion',
    '%FONT%'    => 'font-expansion',
    '%CMD%'     => 'cmd-expansion',
};

# Do the substitutions
foreach my $tid (keys %$tasks)
{
    my $task = $tasks->{$tid};
    my $maps = $task->{maps};
    foreach my $map (keys %$maps)
    {
        foreach my $key (keys %{$task})
        {
            next if ref $task->{$key};
            $task->{$key} =~ s/$map/$maps->{$map}/g;
        }
    }
}

# Demonstration printing
foreach my $tid (keys %$tasks)
{
    my $task = $tasks->{$tid};
    foreach my $key (keys %{$task})
    {
        next if ref $task->{$key};
        printf "%s: %-8s = %s\n", $tid, "$key:", $task->{$key};
    }
}

The output using Perl 5.13.4 on MacOS X (10.6.4) is:

t1: report:  = Launched as cmd-expansion by user-expansion
t1: cmdline: = convert -f font-expansion one-expansion

The triple loop is close to unavoidable; you want to apply each mapping to each string for each of the tasks. Each task can have its own mappings, in general.

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