Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
仅在perl中使用RegExp无限循环,为什么?_Regex_Perl_Loops_Path_Regex Group - Fatal编程技术网

仅在perl中使用RegExp无限循环,为什么?

仅在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单元格有时包含双引号的包装,有时文件名本身需要用双引号包装,因此我

我有一个正则表达式来测试CSV单元格是否包含正确的文件路径:

编辑CSV列出了脚本运行时不存在的文件路径(我不能使用-e),文件路径可以包括*或%variable%或{$variable}

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,是的,脚本应该是这样的