如何在没有替换正则表达式的情况下制作$ 1的返回替代品?

时间:2010-01-22 14:34:45

标签: perl

我最近加入的项目将逻辑抽象为代码和数据库元素。像xPaths,正则表达式和函数名这样的业务逻辑输入到数据库中,而通用代码如读取文件,从xpath创建xml等等都在代码库中。

大多数(如果不是全部)使用正则表达式的方法都是这样构造的:

if ( $entry =~ /$regex/ ) { $req_value = $1; }

这意味着只有1美元可用,您总是必须编写正则表达式,以1美元的价格为您提供所需的结果。

问题:

以下字符串的结果应为

'2.6.9-78.1.6.ELsmp (SMP)' or '2.6.9-78.1.6.ELsmp'

取决于SMP的存在。 $ 1不足以满足$ entry [0]。

$entry[0] = qq|Linux version 2.6.9-78.1.6.ELsmp (brewbuilder@hs20-bc2-2.build.redhat.com) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-10)) #1 SMP Wed Sep 24 05:41:12 EDT 2008|;
$entry[1] = qq|Linux version 2.6.9-78.0.5.ELsmp (brewbuilder@hs20-bc2-2.build.redhat.com) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-10)) #1 Wed Sep 24 05:41:12 EDT 2008|;

因此我的解决方案:

my $mutable = '';
my $regex = qr/((\d.*?)\s+(?:.*)?(SMP)((?{$mutable="$2 ($3)"}))|(\d.*?))\s+/;
if ($entry[$i] =~ /$regex/) {
    $req_value = $1; 
    $req_value = $mutable if ($mutable ne '');
    $mutable = '';
}

不幸的是,数据库中存在“变量”使得该解决方案无法接受。

我的问题是:

  1. 如何清理上述解决方案,使其可用于可用的结构?

  2. 如何使用结构为'if($ entry =〜/ $ regex /)'的替换正则表达式?

  3. 感谢。

3 个答案:

答案 0 :(得分:2)

你被困住了,除非你能说出控制你正在使用的代码的人以某种方式概括它。好消息是你只需要多一点,也许

if (my @fields = $_ =~ /$pat/) {
  $req_value = join " " => grep defined($_), @fields;
}

这是有效的,因为列表上下文中成功的正则表达式匹配会返回所有捕获的子字符串,$1$2$3等等酌情。

使用单一模式

qr/(\d+(?:[-.]\w+)*)(?:.*(SMP))?/

上面的代码会在2.6.9-78.1.6.ELsmp SMP中产生2.6.9-78.0.5.ELsmp$req_valuegrep defined($_)过滤掉未拍摄的子模式。没有它,您将获得非SMP案例的未定义​​值警告。

缺点是需要检查每个正则表达式,以确保所有捕获组确实应该进入$req_value。例如,假设有人使用模式

qr/(XYZ) OS (version \d+|v-\d+)/

就像现在一样,只有XYZ会进入$req_value,但使用上面的概括也会包含版本号。如果这是不希望的,那么正则表达式应该是

qr/(XYZ) OS (?:version \d+|v-\d+)/

因为(?:...)没有捕获(也就是说,它没有为上面的模式生成$2):它仅用于分组。

答案 1 :(得分:0)

我不完全理解你的约束。您是否仅限于提供单个正则表达式,该正则表达式始终使用您的第一个摘录中的代码进行处理?如果是这样,你就无法做你想做的事。您试图提取条目字符串的两个单独部分,您只是不能在单个标量返回值中返回2个值,除非您可以添加代码以连接它们。

你能添加perl代码吗?例如,您可以将逻辑定义为:

if ( $entry =~ /$regex/ ) { $req_value = '$1 $2'; }

你的$regex = qr/((\d.*?)\s+(?:.*)?(SMP)/;

Baring能够定义一些新的perl代码,你无法做到这一点。

关于第二部分,替代。我解释你的问题,问你是否可以将s / PATTERN / REPLACEMENT /的PATTERN和REPLACEMENT部分编译成单个qr //。如果是这样,你就不能。 qr //仅编译匹配模式,qr变量只能用于REPLACEMENT的PATTERN部分。换句话说,要使用s ///,您需要编写运行s ///的perl代码。我猜你是否可以编写新的perl代码,你可以使用上面的解决方案。

还有一个想法:在您当前的架构中,您可以根据其他字段定义字段吗?换句话说,您是否可以使用一个正则表达式提取版本字符串,使用另一个正则表达式提取SMP字符串,并定义组合这两个正则表达式的第三个字段?

答案 2 :(得分:0)

自5.10.0起,(?|pattern)可用于允许替代方案使用相同的捕获编号。当你指出你仍然使用5.8时,这可能没有直接用处,但可能是你的项目开始转向现代Perl的进一步激励。