while()中的全局正则表达式匹配返回结果

前端之家收集整理的这篇文章主要介绍了while()中的全局正则表达式匹配返回结果前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
此脚本将搜索具有单词并打印它们的行,同时在每次迭代中重新读取源文件
# cat mm.pl
#!/usr/bin/perl
use strict;
use warnings;

while( `cat aa` =~ /(\w+)/g ) {
    print "$1\n";
}

输入文件

# cat aa
aa
bb
cc

结果:

# ./mm.pl
aa
bb
cc

请解释我为什么运行脚本不是无止境的.

由于表达式发生变化(新的猫被分叉),所以每次正则表达式引擎的迭代偏移都应该被重置.

我认为perl对猫的结果做了某种缓存,但是strace声称猫被产生了4次(3条为3条1,而条件为假):

# strace -f ./mm.pl 2>&1 | grep cat | grep -v ENOENT
[pid 22604] execve("/bin/cat",["cat","aa"],[/* 24 vars */] <unfinished ...>
[pid 22605] execve("/bin/cat",[/* 24 vars */] <unfinished ...>
[pid 22606] execve("/bin/cat",[/* 24 vars */] <unfinished ...>
[pid 22607] execve("/bin/cat",[/* 24 vars */] <unfinished ...>

另一方面,以下示例永远运行:

# cat kk.pl
#!/usr/bin/perl
use strict;
use warnings;

my $d = 'aaa';
while( $d =~ /(\w+)/g ) {
    print "$1\n";
    $d = 'aaa';
}

两个脚本之间的区别在哪里?我失踪了什么

// g离开的位置存储在魔术中,添加到执行匹配的标量中.
$perl -MDevel::Peek -e'$_ = "abc"; Dump($_); /./g; Dump($_);'
SV = PV(0x32169a0) at 0x3253ee0
  REFCNT = 1
  FLAGS = (POK,IsCOW,pPOK)
  PV = 0x323bae0 "abc"\0
  CUR = 3
  LEN = 10
  COW_REFCNT = 1
SV = PVMG(0x326c040) at 0x3253ee0
  REFCNT = 1
  FLAGS = (SMG,POK,pPOK)
  IV = 0
  NV = 0
  PV = 0x323bae0 "abc"\0
  CUR = 3
  LEN = 10
  COW_REFCNT = 2
  MAGIC = 0x323d050
    MG_VIRTUAL = &PL_vtbl_mglob
    MG_TYPE = PERL_MAGIC_regex_global(g)
    MG_FLAGS = 0x40
      BYTES
    MG_LEN = 1

这意味着在反引号中观察到的行为的唯一方法是示例,如果匹配运算符匹配相同的标量,则四次被评估!怎么可能?这是因为反引号是使用TARG的运算符之一.

创建标量是相对昂贵的,因为它需要最多三个内存分配!为了提高性能,称为TARG的标量与一些运算符的每个实例相关联.当对具有TARG的运算符进行评估时,它可以使用返回的值填充TARG并返回TARG(而不是分配并返回新的值).

“那么什么?”,你可能会问.毕竟,您已经表明,分配到标量将重置与该标量相关联的匹配位置.这是假设发生的,但它不适用于反引号.

魔术不仅允许将信息附加到变量,它还附加在特定条件下被调用功能.由gg添加的魔法附加了一个在标量被修改之后应该调用函数(由上面的转储中的SMG标志指示).当将值分配给标量时,此功能将清除位置.

赋值运算符正确处理魔术,但不能由反驳操作符处理.它并不期望魔法被添加到它的TARG,所以它不检查是否有任何,所以清除匹配位置的功能是不必要的.

原文链接:https://www.f2er.com/regex/357133.html

猜你在找的正则表达式相关文章