Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.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 为什么正则表达式输出错误?_Perl - Fatal编程技术网

Perl 为什么正则表达式输出错误?

Perl 为什么正则表达式输出错误?,perl,Perl,当我运行下面的脚本时,我得到 $VAR1 = [ 'ok0.ok]][[file:ok1.ok', undef, undef, 'ok2.ok|dgdfg]][[file:ok3.ok', undef, undef, undef, undef, undef, undef, und

当我运行下面的脚本时,我得到

$VAR1 = [
          'ok0.ok]][[file:ok1.ok',
          undef,
          undef,
          'ok2.ok|dgdfg]][[file:ok3.ok',
          undef,
          undef,
          undef,
          undef,
          undef,
          undef,
          undef,
          undef,
          undef,
          undef,
          undef,
          undef,
          undef
        ];
我希望
ok0.ok ok1.ok ok2.ok ok3.ok
理想的情况是
ok4.ok ok5.ok ok6.ok ok7.ok

问题

有人能看出我做错了什么吗

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my $html = "sdfgdfg[[file:ok0.ok]][[file:ok1.ok ]] [[file:ok2.ok|dgdfg]][[file:ok3.ok |dfgdfgg]] [[media:ok4.ok]] [[media:ok5.ok ]] [[media:ok6.ok|dgdfg]] [[media:ok7.ok |dfgdfgg]]ggg";

my @seen = ($html =~ /file:(.*?) |\||\]/g);

print Dumper \@seen;

看起来您正在尝试匹配所有内容,从
文件:
开始,以空格、管道或结束方括号结束

您在regexp末尾的OR语句本身需要介于(方)括号之间,但:

my @seen = ($html =~ /file:(.*?)[] |]/g);
如果您想要介质:块,或者文件部分。您可能需要一个非捕获组:

my @seen = ($html =~ /(?:file|media):(.*?)[] |]/g);
工作原理 第一条语句将捕获“file:”和
]
之间的所有内容


第二条语句也有相同的功能,但同时使用文件和媒体。我们使用非捕获组
(?:组)
而不是
(组)
,因此单词不会被放入你的
@seen

我认为否定字符类可以简化一些事情。明确说明锚点(文件:,或媒体:),并明确说明终止序列的内容(空格、管道或右括号)。然后抓捕

my@seen=$html=~m{(文件|媒体):([^\\s\]]+)}g

解释:

my @seen = $html =~ m{
    (?:file|media):        # Match either 'file' or 'media', don't capture, ':'
    ( [^\|\s\]]+ )         # Match and capture one or more, anything except |\s]
}gx;
当遇到
]
|
\s
时,捕获就会停止。

尝试

my @seen = ($html =~ /\[\[\w+:(\w+\.\w+)\]\]/g);

这是您的正则表达式所做的:

 ...
 my $ss = qr {
              file: # start with file + column as anchor
              (         # start capture group
               .*?      # use any character in a non-greedy sweep
              )         # end capture group
              \s        # end non-greedy search on a **white space**

              |     # OR expression encountered up to here with:
              \|     # => | charachter  
              |      # OR expression encountered up to here with:
              \]       # => ] charachter  
              }x;

 my @seen = $html =~ /$ss/g;
 ...
这就是你的正则表达式应该做的:

 ...
 my $rb = qr {
             \w :      # alphanumeric + column as front anchor
             (         # start capture group 
              [^]| ]+  # the terminating sequence
             )         # end capture group 
            }x;

 my @seen = $html =~ /$rb/g;
 ...
如果您想要一个简短的正则表达式,并且知道自己在做什么,您可以完全删除捕获组,并在列表上下文中使用完整的捕获块以及正向查找:

 ...
 my @seen = $html =~ /(?<=(?:.file|media):)[^] |]+/g; # no cature group ()
 ...
问候


rbo

根据文件名中可能的字符,我认为您可能需要

my @seen = $html =~ /(?:file|media):([\w.]+)/g;
它捕获所有的
ok0.ok
ok7.ok


它依赖于包含字母数字字符加下划线和点的文件名。

我希望这是您所需要的

#!/usr/bin/perl

use strict;  

use warnings;

use Data::Dumper;


my $string = "sdfgdfg[[file:ok0.ok]][[file:ok1.ok ]] [[file:ok2.ok|dgdfg]][[file:ok3.ok |dfgdfgg]] [[media:ok4.ok]] [[media:ok5.ok ]] [[media:ok6.ok|dgdfg]] [[media:ok7.ok |dfgdfgg]]ggg";

my @matches;

@matches = $string =~ m/ok\d\.ok/g;

print Dumper @matches;
输出:

$VAR1 = 'ok0.ok';

$VAR2 = 'ok1.ok';

$VAR3 = 'ok2.ok';

$VAR4 = 'ok3.ok';

$VAR5 = 'ok4.ok';

$VAR6 = 'ok5.ok';

$VAR7 = 'ok6.ok';

$VAR8 = 'ok7.ok';
问候,,
基兰

非常有趣。你说的是
(.*?[\]\]\\\]\\\]
而不是
(.*?[\]\\\\\\\\\]
,这是故意的吗?虽然你的解决方案可以满足需要,但你似乎误解了字符类的工作方式。原始正则表达式有
[\]\]\]\]
,它与列表中的任何右括号、管道、右括号、管道或空格匹配。现在,您的修订与管道、管道、闭合括号、管道或空间相匹配。您所需要的是
[]|]
,它匹配右括号、管道或空格。@Borodin:我确实把字符类和组混淆了。字符类中不需要管道或字符
[]
。谢谢现在我很困惑。为什么Perl不抱怨
(.*?[]|]
的括号不平衡?我的意思是,它如何知道第一个
]
是要匹配的字符,而不是字符类的结尾?@sandraschliching-pease read Section:
[^\\s\]
中带括号的字符类中的特殊字符减少为
[^]\s\]
(或
[^]|]
如果您无法忍受字符类中的退格;-)。
$VAR1 = 'ok0.ok';

$VAR2 = 'ok1.ok';

$VAR3 = 'ok2.ok';

$VAR4 = 'ok3.ok';

$VAR5 = 'ok4.ok';

$VAR6 = 'ok5.ok';

$VAR7 = 'ok6.ok';

$VAR8 = 'ok7.ok';