2

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

$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;
4

6 回答 6

2

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

my @seen = $html =~ m{(?:file|media):([^\|\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

于 2012-06-26T09:39:50.247 回答
1

尝试

my @seen = ($html =~ /\[\[\w+:(\w+\.\w+)\]\]/g);
于 2012-06-26T09:41:16.783 回答
1

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

 ...
 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 ()
 ...

或者,如果您的数据中没有其他结构需要处理,请使用:as only 锚:

 ...
 my @seen = $html =~ /(?<=:)[^] |]+/g;   # no capture group and short
 ...

问候

rbo

于 2012-06-26T10:18:17.390 回答
1

看起来您正在尝试匹配file:以空格、管道或右方括号开头和结尾的所有内容。

不过,您在正则表达式末尾的 OR 语句需要位于(方)括号之间:

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

如果你想要 media: 块,或者文件部分。您可能需要一个非捕获组:

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

这个怎么运作

第一条语句将捕获 'file:' 和 a 或 之间的]所有|内容

第二条语句的作用相同,但同时使用了filemedia。我们使用非捕获组(?:group)代替,(group)因此不会将单词放入您的@seen.

于 2012-06-26T09:37:51.423 回答
0

根据文件名中可能的字符,我想你可能想要

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

它捕获了所有ok0.okok7.ok.

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

于 2012-06-26T10:27:01.083 回答
0

我希望这是你所需要的。

#!/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';

问候,基兰。

于 2012-06-26T12:06:27.977 回答