仅在perl中使用RegExp无限循环,为什么?
我有一个正则表达式来测试CSV单元格是否包含正确的文件路径: 编辑CSV列出了脚本运行时不存在的文件路径(我不能使用-e),文件路径可以包括*或%variable%或{$variable}仅在perl中使用RegExp无限循环,为什么?,regex,perl,loops,path,regex-group,Regex,Perl,Loops,Path,Regex Group,我有一个正则表达式来测试CSV单元格是否包含正确的文件路径: 编辑CSV列出了脚本运行时不存在的文件路径(我不能使用-e),文件路径可以包括*或%variable%或{$variable} my $FILENAME_REGEXP = '^(|"|""")(?:[a-zA-Z]:[\\\/])?[\\\/]{0,2}(?:(?:[\w\s\.\*-]+|\{\$\w+}|%\w+%)[\\\/]{0,2})*\1$'; 由于CSV单元格有时包含双引号的包装,有时文件名本身需要用双引号包装,因此我
my $FILENAME_REGEXP = '^(|"|""")(?:[a-zA-Z]:[\\\/])?[\\\/]{0,2}(?:(?:[\w\s\.\*-]+|\{\$\w+}|%\w+%)[\\\/]{0,2})*\1$';
由于CSV单元格有时包含双引号的包装,有时文件名本身需要用双引号包装,因此我对其进行了分组(|“|””“”)\一,
然后使用此功能:
sub ValidateUNCPath{
my $input = shift;
if ($input !~ /$FILENAME_REGEXP/){
return;
}
else{
return "This is a Valid File Path.";
}
}
我正在尝试测试此短语是否与我的regexp匹配(不应匹配):
但我亲爱的Perl在以下情况下进入无限循环:
ValidateUNCPath('"""c:\my\dir\lord"');
编辑实际上,它会在此循环:
ValidateUNCPath('"""\aaaaaaaaa\bbbbbbb\ccccccc\Netwxn00.map"');
我确保我的regexp正确捕获了那些非对称的“…”双引号,但Perl有自己的想法:(
我甚至在中尝试了/g和/o标志
/$FILENAME_REGEXP/go
但是它仍然挂起。我遗漏了什么?首先,您发布的任何内容都不会导致无限循环,因此如果您得到了无限循环,那么它不是来自代码的这一部分 当我尝试使用您的子例程时,对于所有看起来不像路径的字符串,它都会返回true,例如:
.....
This is a Valid File Path.
.*.*
This is a Valid File Path.
-
This is a Valid File Path.
这是因为你的正则表达式很松散
^(|"|""") # can match the empty string
(?:[a-zA-Z]:[\\\/])? # same, matches 0-1 times
[\\\/]{0,2} # same, matches 0-2 times
(?:(?:[\w\s\.\*-]+|\{\$\w+}|%\w+%)[\\\/]?)+\1$ # only this is not optional
由于实际上只有最后一部分必须匹配任何内容,因此允许使用各种字符串,主要是在第一个字符类中:[\w\s\.\*-]
在我个人看来,当你开始依赖看起来像你的正则表达式时,你是做错了什么。除非你精通正则表达式,并且希望没有人会被迫修复它
为什么不删除引号呢?另外,如果系统中存在此路径,那么有一种更简单的方法来检查它是否有效:首先,您发布的任何内容都不会导致无限循环,因此,如果您得到的是无限循环,则它不是来自代码的这一部分 当我尝试使用您的子例程时,对于所有看起来不像路径的字符串,它都会返回true,例如:
.....
This is a Valid File Path.
.*.*
This is a Valid File Path.
-
This is a Valid File Path.
这是因为你的正则表达式很松散
^(|"|""") # can match the empty string
(?:[a-zA-Z]:[\\\/])? # same, matches 0-1 times
[\\\/]{0,2} # same, matches 0-2 times
(?:(?:[\w\s\.\*-]+|\{\$\w+}|%\w+%)[\\\/]?)+\1$ # only this is not optional
由于实际上只有最后一部分必须匹配任何内容,因此允许使用各种字符串,主要是在第一个字符类中:[\w\s\.\*-]
在我个人看来,当你开始依赖看起来像你的正则表达式时,你是做错了什么。除非你精通正则表达式,并且希望没有人会被迫修复它
为什么不删除引号呢?另外,如果系统中存在此路径,那么有一种更简单的方法来检查它是否有效:更新 编辑:根据反复试验,下面的分组子表达式
[\w\s.*-]+
导致回溯问题
(?:
(?:
[\w\s.*-]+
| \{\$\w+\}
| %\w+%
)
[\\\/]?
)+
修正#1,
展开法
'
^
( # Nothing
|" # Or, "
|""" # Or, """
)
# Here to end, there is no provision for quotes (")
(?: # If there are no balanced quotes, this will fail !!
[a-zA-Z]
:
[\\\/]
)?
[\\\/]{0,2}
(?:
[\w\s.*-]
| \{\$\w+\}
| %\w+%
)+
(?:
[\\\/]
(?:
[\w\s.*-]
| \{\$\w+\}
| %\w+%
)+
)*
[\\\/]?
\1
$
'
Fix#2,独立子表达式
'
^
( # Nothing
|" # Or, "
|""" # Or, """
)
# Here to end, there is no provision for quotes (")
(?: # If there are no balanced quotes, this will fail !!
[a-zA-Z]
:
[\\\/]
)?
[\\\/]{0,2}
(?>
(?:
(?:
[\w\s.*-]+
| \{\$\w+\}
| %\w+%
)
[\\\/]?
)+
)
\1
$
'
修复#3,移除+量词(或添加+?)
更新 编辑:根据反复试验,下面的分组子表达式
[\w\s.*-]+
导致回溯问题
(?:
(?:
[\w\s.*-]+
| \{\$\w+\}
| %\w+%
)
[\\\/]?
)+
修正#1,
展开法
'
^
( # Nothing
|" # Or, "
|""" # Or, """
)
# Here to end, there is no provision for quotes (")
(?: # If there are no balanced quotes, this will fail !!
[a-zA-Z]
:
[\\\/]
)?
[\\\/]{0,2}
(?:
[\w\s.*-]
| \{\$\w+\}
| %\w+%
)+
(?:
[\\\/]
(?:
[\w\s.*-]
| \{\$\w+\}
| %\w+%
)+
)*
[\\\/]?
\1
$
'
Fix#2,独立子表达式
'
^
( # Nothing
|" # Or, "
|""" # Or, """
)
# Here to end, there is no provision for quotes (")
(?: # If there are no balanced quotes, this will fail !!
[a-zA-Z]
:
[\\\/]
)?
[\\\/]{0,2}
(?>
(?:
(?:
[\w\s.*-]+
| \{\$\w+\}
| %\w+%
)
[\\\/]?
)+
)
\1
$
'
修复#3,移除+量词(或添加+?)
如果正则表达式引擎很幼稚
('y') x 20 =~ /^.*.*.*.*.*x/
要失败需要很长时间,因为它必须尝试
20 * 20 * 20 * 20 * 20 = 3,200,000 possible matches.
您的模式具有类似的结构,这意味着它有许多组件匹配输入的广泛子字符串
现在,Perl的正则表达式引擎得到了高度优化,远远不是幼稚的。在上面的模式中,它将从查找x
开始,并非常快地退出。不幸的是,它没有或不能同样优化您的模式
你的模式完全是一团糟。我甚至不会去猜测它应该匹配什么。你会发现,一旦你切换到正确的模式,这个问题就会自行解决。如果正则表达式引擎很幼稚
('y') x 20 =~ /^.*.*.*.*.*x/
要失败需要很长时间,因为它必须尝试
20 * 20 * 20 * 20 * 20 = 3,200,000 possible matches.
您的模式具有类似的结构,这意味着它有许多组件匹配输入的广泛子字符串
现在,Perl的正则表达式引擎得到了高度优化,远远不是幼稚的。在上面的模式中,它将从查找x
开始,并非常快地退出。不幸的是,它没有或不能同样优化您的模式
你的模式完全是一团糟。我甚至不打算猜测它应该匹配什么。你会发现,一旦你切换到正确的模式,这个问题就会自行解决。多亏了sln,这是我的固定regexp:
my $FILENAME_REGEXP = '^(|"|""")(?:[a-zA-Z]:[\\\/])?[\\\/]{0,2}(?:(?:[\w\s.-]++|\{\$\w+\}|%\w+%)[\\\/]{0,2})*\*?[\w.-]*\1$';
(我也不允许在目录中使用*字符,只允许在(最后一个)文件名中使用单个*字符)多亏了sln,这是我的固定regexp:
my $FILENAME_REGEXP = '^(|"|""")(?:[a-zA-Z]:[\\\/])?[\\\/]{0,2}(?:(?:[\w\s.-]++|\{\$\w+\}|%\w+%)[\\\/]{0,2})*\*?[\w.-]*\1$';
(我还禁止在目录中使用*字符,只允许在(最后一个)文件名中使用单个*字符)您发布的任何代码都不会导致无限循环。请不要返回,而是尝试返回“”;语法
if(…)return;else return;
会在perl中导致语法错误…为什么不粘贴真实代码,包括您正在使用的循环,那么我们可能可以帮助您。@noamanos您尚未粘贴显示无限循环的代码。0\u 0为什么不使用来获取每行中的字段,然后用它测试文件路径?没有代码y您已经发布了可能导致无限循环的内容。请尝试返回“”;语法if(…)return;else return;
会在perl中导致语法错误…为什么不粘贴真实代码,包括您正在使用的循环,那么我们可能可以帮助您。@noamanos您还没有粘贴到显示无限循环的代码中。0\u 0为什么不使用来获取每行中的字段,然后使用所有测试来测试文件路径具有完全有效的相对文件路径,因此它们不会显示正则表达式已损坏。@RobKennedy我不认为任何由[\w\s\.\*-]+
组成的字符串都是有效路径。您的每个测试都符合该正则表达式,并且每个测试都是有效的相对路径。@RobKennedy这些示例如何?@TLP hmmm,是的,脚本应该是这样的