繁体   English   中英

如何排除与Perl正则表达式匹配的字符串部分?

[英]How can I exclude the part of the string that matches a Perl regular expression?

我必须归档具有不同类型的线。 我只想选择那些具有用户代理的行。 我知道具有这种功能的生产线就是这样。

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.8.1.16) Gecko/20080702 Firefox/2.0.0.16

因此,我想确定以字符串“ User-Agent”开头的行,但此后,我要处理该字符串以外的其余部分。 我的问题是Perl是否将剩余的字符串存储在任何可用于进一步处理的特殊变量中? 因此,基本上,我想匹配以该字符串开头的行,但在此之后的其余部分(不包括该字符串)进行处理。

我用一个简单的正则表达式搜索该行

/^User-Agent:/
if ($line =~ /^User\-Agent\: (.*?)$/) {
    &process_string($1)
}

(我的$ remainder = $ str)=〜s / ^ User-Agent://;

substr解决方案:

my $start = "User-Agent: ";

if ($start eq substr $line, 0, length($start)) {
    my $remainder = substr $line, length($start);
}

您可以使用$'变量,但不要使用 -这会增加很多开销。 出于相同的目的,可能@LAST_MATCH_END@+变量,或者用英语来说是@LAST_MATCH_END

因此,这将使您到达那里:

use English qw<@LAST_MATCH_END>;

my $value = substr( $line, $LAST_MATCH_END[0] );

Perl 5.10具有一个不错的功能,使您能够获得$'解决方案的简单性而不会出现性能问题。 您使用/p标志和${^POSTMATCH}变量:

 use 5.010;
 if( $string =~ m/^User-Agent:\s+/ip ) {
      my $agent = ${^POSTMATCH};
      say $agent;
      }

但是,还有其他一些技巧。 如果您不能使用Perl 5.010或更高版本,则在标量上下文中使用全局匹配,则pos的值就是您在字符串中保留的位置。 您可以在substr中使用该位置:

 if( $string =~ m/^User-Agent:\s+/ig ) {
      my $agent = substr $string, pos( $string );
      print $agent, "\n";
      }

posAxeman显示@+技巧相似。 我想在第一章的Mastering Perl中有@+@-一些示例。

对于即将推出的Perl 5.14,还有另一种有趣的方法可以做到这一点。 s///上的/r标志进行无损替换 也就是说,它匹配绑定的字符串,但是对副本执行替换并返回副本:

use 5.013;  # for now, but 5.014 when it's released
my $string = 'User-Agent: Firefox';
my $agent = $string =~ s/^User-Agent:\s+//r;
say $agent;

我以为/r起初很傻,但是我真的开始喜欢它。 事实证明,这么多事情真的很容易。 这类似于M42所示的惯用法 ,但是有点棘手,因为旧惯用法先执行赋值然后进行替换,其中/r功能执行替换后进行赋值。 您必须小心括号,以确保顺序正确。

请注意,在这种情况下,由于版本是Perl 5.12或更高版本,因此您会自动获得约束

您可以使用$'捕获字符串的匹配后部分:

if ( $line =~ m/^User-Agent: / ) {
    warn $';
}

(请注意,冒号后面有一个尾随空格。)

但是请注意,来自perlre

警告:一旦Perl在程序中的任何位置看到您需要$&,$`或$'中的一个,它就必须为每个模式匹配提供它们。 这可能会大大降低您的程序速度。 Perl使用相同的机制来产生$ 1,$ 2等,因此您还为包含捕获括号的每个模式付出了代价。 (为避免在保留分组行为的同时避免这种开销,请改用扩展的正则表达式(?:...)。)但是,如果您从不使用$&,$`或$',则不捕获括号的模式将不会受到惩罚。 因此,如果可以的话,请避免使用$&,$'和$`,但如果不能(并且某些算法真的很欣赏它们),则一旦使用了它们,就可以随意使用它们,因为您已经支付了价钱。 从5.005开始,$&的价格不及其他两个昂贵。

使用$'将字符串的一部分移到匹配项的右边。

关于“相当大的性能损失”的其他答案中有很多痛苦的话题,但是除非您实际上知道您的程序大量使用正则表达式,并且您遇到了性能问题,否则我不必担心。

我们经常担心对实际代码几乎没有影响的优化。 很有可能,这也是其中之一。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM