如何在正则表达式perl中匹配一次

时间:2010-10-20 15:47:28

标签: regex perl split

$line = " TEST: asdas :asd asdasad s";

if ($line =~ /(.*):(.*)/
{
  print "$1  = $2 "
}

我期待TEST =asdas :asd asdasad s

但它不起作用?什么是问题

5 个答案:

答案 0 :(得分:12)

正确的方法是:

/([^:]+):(.*)/

/(.+?):(.*)/

这样,你不匹配左边的“任何东西”,你在第一个例子中匹配“一个或多个非冒号字符”,或者“匹配任意字符后跟冒号的最短字符串” “在第二个。

更好的方法是不使用正则表达式。使用split

my ($left,$right) = split( /:/, $line, 2 );

,2说“我最多需要两个字段”。

答案 1 :(得分:4)

问题是,正如其他人所说的那样,除了结尾贪婪 (.*)之外的所有内容都匹配。但他们没有告诉你,当正则表达式引擎匹配到行尾的所有内容时,它必须回溯以满足':'条件。因此,在吞下所有非换行字符后,它开始备份。由于它现在正在反向,它找到的第一个冒号是'as'之前的':'。冒号已经匹配,它将第二组应用于它满足的所有非换行符。

每当你可以,你想避免在正则表达式中回溯。由于您希望它匹配第一个冒号,因此它之前的所有其他内容都不应该是冒号。因此,非回溯,行列式表达式将是:

([^:]+):(.*)

一旦你看到第一个冒号,贪婪的比赛就好了。但是,如果你有一个空格和非空格的字符串并且你想匹配到最后一个非空格 - 因此修剪字符串 - 你无法真正指明这一点这不会回溯,因为你知道你是否只想通过理解角色作为整体的一部分而想要一个单独的角色。

([^:]+):(.*\S)

当它到达输入的末尾时,它会回溯到仍未匹配的非空格。当它发现时,它会终止捕获。

当然这是一个简单的例子,替代表达式可以减少回溯。您可能知道只接受单个空格字符,因此您可以创建一个最多只能回溯一次的表达式,但只能结束匹配:

([^:]+):((?:\S| \S)+)

这里看下一个字符:如果它不是空格,没问题;如果它是一个空格,那么只需要再读一个字符以确定它是否是一个守护者。并且由于空间跟随非空间是最后一个选项,它会失败并完成匹配。

This post from Regex Guru对此有更多了解。

答案 2 :(得分:2)

两个问题:

  1. 您在)声明的最后需要一个右括号if
  2. 您希望 -greedy表达式匹配第一个冒号(:
  3. 之前的最少数量

    尝试$line =~ m/(.*?):(.*)/ - 请注意.*? - 这意味着匹配最低要求。通常.*表示匹配最大可能

答案 3 :(得分:1)

使第一个.*非贪婪也会起作用:

if ($line =~ /(.*?):(.*)/) {
  print "$1  = $2 "
}

答案 4 :(得分:1)

$line = " TEST: asdas :asd asdasad s";

if ($line =~ /(.*?):(.*)/)
{
    print "$1  = $2 "
}

使用以上代替。这里(。*?)表示非贪婪的匹配。所以它会匹配,直到找到第一个':'