匹配作为数组而不是变量返回

时间:2015-11-17 15:25:58

标签: regex perl

我从两个类似XML的标签之间拉出一个简单的字符串,但匹配是作为数组而不是变量返回的。我使用以下代码:

NA

$finishState = $inFileLine =~ m(<State>(.*?)<\/State>)g; 的值是:

$inFileLine

当我运行此代码时,&#34; 1&#34;存储在<recordNum>SW001</recordNum><state>Assigned</state><title>Fix Something</title> 中。当我将$finishState更改为$finishState时,值为&#34;已分配&#34;存储得当。

我不确定为什么以及如何解决这个问题。我绝对不能使用XML解析器。

虽然在数组中拥有我需要的值并不会杀死我,但我想知道为什么会发生这种情况并修改我的正则表达式以正确填充变量。我也考虑过使用grep,sed,awk等,但匹配似乎是一种简洁明了的方法。

3 个答案:

答案 0 :(得分:3)

$finishState = $inFileLine =~ m(<State>(.*?)<\/State>)g;

在标量上下文中计算正则表达式,并使用true(1)或false($finishState)值填充""

@finishState = $inFileLine =~ m(<State>(.*?)<\/State>)g;

甚至

($finishState) = $inFileLine =~ m(<State>(.*?)<\/State>)g;

评估列表上下文中的正则表达式。标量上下文和列表上下文之间的区别在Perl中很重要,也是新Perl程序员混淆的最大原因之一。许多函数和操作在两个不同的上下文中表现不同,并且通常唯一的方法是确定操作在特定上下文中应该执行的操作是read the docs

In this case@finishState将由正则表达式中与捕获组匹配的所有字符串的列表填充(即,<State>和{</State>和{{{}}所涵盖的所有长度为0的字符串{1}}标记),在您的示例中是一个值为Assigned的元素的列表。

答案 1 :(得分:3)

它被称为上下文。 Perl是基于上下文的语言,操作数给出的结果基于您正在评估它的上下文。

perl中有两种类型的上下文。

  1. 标量上下文。
  2. 列出上下文。
  3. 列表是标量的集合。我们使用数组和散列来命名它们。

    my $finishState = $inFileLine =~ m(<State>(.*?)<\/State>)g;
    

    在这种情况下,您正在评估标量上下文中的表达式,该表达式为您提供布尔值,无论它是否匹配,例如您的1(matched)

    my @finishState = $inFileLine =~ m(<State>(.*?)<\/State>)g;
    

    在这种情况下,您将表达式计算为数组,因此它将为您提供数组中的所有匹配项。

    因此,您知道只有一个匹配项,并且您希望将其存储到标量使用parenthesis中以在列表上下文中对其进行评估。

    my ($finishState) = $inFileLine =~ m(<State>(.*?)<\/State>)g;
    

    现在$finishState将包含您的匹配。

    如果有多个匹配项,则$finishState将包含第一个匹配项。检查thisthis节点以获取有关上下文的更多信息。

答案 2 :(得分:1)

通常您会引用$1来查看第一个匹配括号的内容:

$inFileLine = '<recordNum>SW001</recordNum><state>Assigned</state><title>Fix Something</title>';
$inFileLine =~ m(<State>(.*?)<\/State>)i;
$finishState = $1;
print $finishState;

输出

  

分配

perlrequick表示

  

在列表上下文中,// g返回匹配分组的列表,如果没有分组,则返回整个正则表达式的匹配列表。

但通常的方法是检查正则表达式的返回值以确定是否存在任何匹配,并引用$1$2等来查看匹配项。