搜索全局变量时 perl 正则表达式不一致
perl regex is inconsistent when searching through global variable
我有一个简单的 perl 脚本查询数据库视图的 dml(如果它看起来很奇怪,请忽略 db->query 位 - 我没有使用 DBI 库),然后将其存储在全局变量中
my $dmlRef = $db->query($sql) || die "cannot query the db $! \n for sql: $sql";
our $dml = $dmlRef->[0]->{'DML'};
当我在子程序中打印此 dml (print "$main::dml\n") 时,它看起来像这样:
"...来自 schema.MY_CALL_LOG..."
dml是一系列常见的table表达式,所以里面提到了很多模式,风格和上面一样。
所以我有一个 sub,我尝试使用全局变量查找我的模式列表是否在其中,我将 dml 保存到:
sub is_in_view_dll {
my $schema = shift || die "no schema passed in";
if ($main::dml =~ m/FROM\s+$schema\.MY_CALL_LOG/ig){ ##use global variable $dml here
print "found $schema in dml!\n";
}else{
print "couldn't find $schema in dml \n";
}
当我使用它时,我发现 perl 无法正则表达式匹配我列表中的一些模式名称,尽管我检查了 a) 它们在 dml 中 b) 大小写在我的模式列表中匹配(模式名称中没有空格)
当我创建全局 $dml 变量的本地副本时,我发现 perl 正则表达式按预期工作
sub is_in_view_dll {
my $schema = shift || die "no schema passed in";
my $localdml = "$main::dml";
if ($localdml =~ m/FROM\s+$schema\.MY_CALL_LOG/ig){ ##search through local copy of global var
print "found $schema in dml!\n"; ##works correctly
}else{
print "couldn't find $schema in dml \n";
}
我不明白为什么直接使用全局变量“$main::dml”对所有匹配尝试都不起作用,而在子的正则表达式中使用它的本地副本却起作用
更多信息/如何复制
我创建了一个精简示例,其中我可以复制这个问题(希望你也可以),其中正在生成的 data/input 作为字符串存储在我们的 $dml 变量中:
#!/usr/bin/perl -I/usr/local/lib/perl
use strict;
use Data::Dumper;
our $dml = <<EOM
CREATE OR REPLACE FORCE EDITIONABLE VIEW "GWMONITORING"."MY_CALL_LOG" ("OWNER", "DAY", "HOUR", "USERNAME", "CALL_ID") AS
SELECT
'DEMOGW' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
DEMOGW.MY_CALL_LOG
UNION ALL
SELECT
'ARMYS' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
ARMYS.MY_CALL_LOG
UNION ALL
SELECT
'GFW' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GFW.MY_CALL_LOG
UNION ALL
SELECT
'GLOBE' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GLOBE.MY_CALL_LOG
UNION ALL
SELECT
'VARS' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
VARS.MY_CALL_LOG
UNION ALL
SELECT
'ALLHH' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
ALLHH.MY_CALL_LOG
UNION ALL
SELECT
'GW' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GW.MY_CALL_LOG
UNION ALL
SELECT
'QUEEN' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
QUEEN.MY_CALL_LOG
UNION ALL
SELECT
'GEORGEY' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GEORGEY.MY_CALL_LOG
UNION ALL
SELECT
'MONKEYS' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
MONKEYS.MY_CALL_LOG
UNION ALL
SELECT
'MYPAQS' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
MYPAQS.MY_CALL_LOG
UNION ALL
SELECT
'GWINV' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GWINV.MY_CALL_LOG
UNION ALL
SELECT
'PRIMER' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
PRIMER.MY_CALL_LOG
UNION ALL
SELECT
'GWSTIM' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GWSTIM.MY_CALL_LOG
UNION ALL
SELECT
'GFW2' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GFW2.MY_CALL_LOG
UNION ALL
SELECT
'GPETW' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GPETW.MY_CALL_LOG
UNION ALL
SELECT
'GWAHG' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GWAHG.MY_CALL_LOG
EOM
;
my @schemas = qw(GW GWAHG GPETW GFW2 GFW GWSTIM DEMOGW GWINV GLOBE PRIMER ARMYS MONKEYS QUEEN VARS ALLHH MYPAQS GEORGEY );
foreach(@schemas){
is_in_view($_);
}
sub is_in_view {
my $owner = shift || die "no owner passed in";
my $localdml = "$main::dml";
if ($localdml !~ m/FROM\s+$owner\.MY_CALL_LOG/ig){ ##when you use this line, should find no matches fail to be found
#if ($main::dml !~ m/FROM\s+$owner\.MY_CALL_LOG/ig){ ##when you use this line, should find that some matches fail to be found. For me this was GPETW, GFW DEMOGW GLOBE ARMYS QUEEN GEORGEY
print "$owner is not in the dml for GWMONITORING\.MY_CALL_LOG\n";
}
}
这是正则表达式引擎,它存储最后一个位置并从该位置开始下一场比赛(在 /g 下):
#!/bin/env perl
use strict;
use warnings;
my $string = 'bar foo bar baz';
for my $pat (qw/bar foo bar foo/){
if ($string =~ /$pat/g){
print "\nmatch for $pat\n"
}
else{
print "\nno match for $pat\n"
}
print pos $string;
}
打印:
match for bar
3
match for foo
7
match for bar
11
no match for foo
Use of uninitialized value in print at command.pl line 13.
最后的匹配会失败,因为在字符串中的 pos 11 之后没有 'foo'。
如果您将 pos $main::dml
的调试打印添加到您的函数或每次 pos($main::dml) = 0;
重置 pos,您将看到效果。
请注意,匹配失败后 pos 会重置。
参考perlrequick。
我有一个简单的 perl 脚本查询数据库视图的 dml(如果它看起来很奇怪,请忽略 db->query 位 - 我没有使用 DBI 库),然后将其存储在全局变量中
my $dmlRef = $db->query($sql) || die "cannot query the db $! \n for sql: $sql";
our $dml = $dmlRef->[0]->{'DML'};
当我在子程序中打印此 dml (print "$main::dml\n") 时,它看起来像这样:
"...来自 schema.MY_CALL_LOG..."
dml是一系列常见的table表达式,所以里面提到了很多模式,风格和上面一样。
所以我有一个 sub,我尝试使用全局变量查找我的模式列表是否在其中,我将 dml 保存到:
sub is_in_view_dll {
my $schema = shift || die "no schema passed in";
if ($main::dml =~ m/FROM\s+$schema\.MY_CALL_LOG/ig){ ##use global variable $dml here
print "found $schema in dml!\n";
}else{
print "couldn't find $schema in dml \n";
}
当我使用它时,我发现 perl 无法正则表达式匹配我列表中的一些模式名称,尽管我检查了 a) 它们在 dml 中 b) 大小写在我的模式列表中匹配(模式名称中没有空格)
当我创建全局 $dml 变量的本地副本时,我发现 perl 正则表达式按预期工作
sub is_in_view_dll {
my $schema = shift || die "no schema passed in";
my $localdml = "$main::dml";
if ($localdml =~ m/FROM\s+$schema\.MY_CALL_LOG/ig){ ##search through local copy of global var
print "found $schema in dml!\n"; ##works correctly
}else{
print "couldn't find $schema in dml \n";
}
我不明白为什么直接使用全局变量“$main::dml”对所有匹配尝试都不起作用,而在子的正则表达式中使用它的本地副本却起作用
更多信息/如何复制
我创建了一个精简示例,其中我可以复制这个问题(希望你也可以),其中正在生成的 data/input 作为字符串存储在我们的 $dml 变量中:
#!/usr/bin/perl -I/usr/local/lib/perl
use strict;
use Data::Dumper;
our $dml = <<EOM
CREATE OR REPLACE FORCE EDITIONABLE VIEW "GWMONITORING"."MY_CALL_LOG" ("OWNER", "DAY", "HOUR", "USERNAME", "CALL_ID") AS
SELECT
'DEMOGW' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
DEMOGW.MY_CALL_LOG
UNION ALL
SELECT
'ARMYS' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
ARMYS.MY_CALL_LOG
UNION ALL
SELECT
'GFW' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GFW.MY_CALL_LOG
UNION ALL
SELECT
'GLOBE' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GLOBE.MY_CALL_LOG
UNION ALL
SELECT
'VARS' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
VARS.MY_CALL_LOG
UNION ALL
SELECT
'ALLHH' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
ALLHH.MY_CALL_LOG
UNION ALL
SELECT
'GW' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GW.MY_CALL_LOG
UNION ALL
SELECT
'QUEEN' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
QUEEN.MY_CALL_LOG
UNION ALL
SELECT
'GEORGEY' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GEORGEY.MY_CALL_LOG
UNION ALL
SELECT
'MONKEYS' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
MONKEYS.MY_CALL_LOG
UNION ALL
SELECT
'MYPAQS' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
MYPAQS.MY_CALL_LOG
UNION ALL
SELECT
'GWINV' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GWINV.MY_CALL_LOG
UNION ALL
SELECT
'PRIMER' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
PRIMER.MY_CALL_LOG
UNION ALL
SELECT
'GWSTIM' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GWSTIM.MY_CALL_LOG
UNION ALL
SELECT
'GFW2' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GFW2.MY_CALL_LOG
UNION ALL
SELECT
'GPETW' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GPETW.MY_CALL_LOG
UNION ALL
SELECT
'GWAHG' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GWAHG.MY_CALL_LOG
EOM
;
my @schemas = qw(GW GWAHG GPETW GFW2 GFW GWSTIM DEMOGW GWINV GLOBE PRIMER ARMYS MONKEYS QUEEN VARS ALLHH MYPAQS GEORGEY );
foreach(@schemas){
is_in_view($_);
}
sub is_in_view {
my $owner = shift || die "no owner passed in";
my $localdml = "$main::dml";
if ($localdml !~ m/FROM\s+$owner\.MY_CALL_LOG/ig){ ##when you use this line, should find no matches fail to be found
#if ($main::dml !~ m/FROM\s+$owner\.MY_CALL_LOG/ig){ ##when you use this line, should find that some matches fail to be found. For me this was GPETW, GFW DEMOGW GLOBE ARMYS QUEEN GEORGEY
print "$owner is not in the dml for GWMONITORING\.MY_CALL_LOG\n";
}
}
这是正则表达式引擎,它存储最后一个位置并从该位置开始下一场比赛(在 /g 下):
#!/bin/env perl
use strict;
use warnings;
my $string = 'bar foo bar baz';
for my $pat (qw/bar foo bar foo/){
if ($string =~ /$pat/g){
print "\nmatch for $pat\n"
}
else{
print "\nno match for $pat\n"
}
print pos $string;
}
打印:
match for bar
3
match for foo
7
match for bar
11
no match for foo
Use of uninitialized value in print at command.pl line 13.
最后的匹配会失败,因为在字符串中的 pos 11 之后没有 'foo'。
如果您将 pos $main::dml
的调试打印添加到您的函数或每次 pos($main::dml) = 0;
重置 pos,您将看到效果。
请注意,匹配失败后 pos 会重置。
参考perlrequick。