捕获两个字符之间的子字符串?

时间:2018-06-30 00:14:37

标签: regex perl

我正在尝试编写一个正则表达式模式,该模式将捕获两个字符之间的子字符串。字符串是

default_checks/my_checks/VLG6.3: Unsupported system function call

我需要捕获VLG6.3。它在斜杠/和冒号:之间。

我尝试了这些想法

my $rule = $line =~ /\/(.*)\:/;
my $rule = $line =~ /\/(.+?)\:/ ;
my $rule = $line =~ /\/(\w+)\:/ ; 

但是它们都不起作用。最好的情况下,我得到my_checks/VLG6.3

4 个答案:

答案 0 :(得分:3)

除了ikegami指出的给标量分配列表的问题外,regex模式还可以使用一些固定方法。

正则表达式中的转发器*是贪婪的。只要匹配,它就会吞噬尽可能多的字符。您需要让另一个中继器预先进行吞噬,以便仅留给您真正想要匹配的中继器。

my ($rule) = $line =~ /.*\/(.*):/;

或者,在这种情况下,您可以使用排除类而不是匹配任何字符。

my ($rule) = $line =~ /\/([^\/]*):/;

以上两种情况都将以$rule分配给'VLG6.3'来结束。

答案 1 :(得分:2)

您对满足以下条件的非空字符串感兴趣:

  • 前面带有/
  • 其后是一个冒号。
  • 它既不包含/,也不包含冒号。

因此,没有任何捕获组的直观正则表达式为: (?<=\/)[^\/:]+(?=:)(正向后看,实际内容 和积极向前看。

使用这样的正则表达式,您可以:

  • 仅使用=~运算符的结果 来检查是否已 匹配。
  • $&变量中打印匹配的文本。

示例脚本如下所示:

use strict;
use warnings;

my $line = 'default_checks/my_checks/VLG6.3: Unsupported system function call';
print "Source: $line\n";
if ($line =~ /(?<=\/)[^\/:]+(?=:)/) {
    print "Rule: $&\n";
} else {
    print "No match.\n";
}

答案 2 :(得分:1)

获得1的原因是因为您正在标量上下文中评估匹配项。为了使匹配返回捕获结果,需要在列表上下文中对其进行评估。

您需要通过在列表上下文中评估=~来评估列表上下文中的匹配项。与您使用的标量赋值运算符不同,列表赋值运算符在列表上下文中评估其操作数。通过将my $rule替换为my ($rule),可以使列表赋值运算符被使用。

my ($rule) = $line =~ /\/(.*)\:/;

请参见Why are there parentheses around scalar when assigning the return value of regex match in this Perl snippet?


此外,匹配运算符将抓取更多的期望值。您可以通过替换

来解决
/\/(.*)\:/

使用

/\/([^\/]*)\:/

我将这样写:

m{/([^/]*):}

答案 3 :(得分:0)

要捕获两个字符之间的字符串,请捕获非两个字符的所有内容。

my $line = 'default_checks/my_checks/VLG6.3: Unsupported system function call';
my ( $rule ) = $line =~ /\/([^\/:]*):/;
print "$rule\n";

PS:要捕获两个字符串之间的内容,需要跳过起始字符串的序列。

my $line = 'begin not this begin or this begin wanted end not this end or this end';
my ( $rule ) = $line =~ m{ (?: begin .* )? begin (.*?) end }msx;
print "$rule\n";