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
Regex 全局匹配正则表达式_Regex_Perl_Freeze - Fatal编程技术网

Regex 全局匹配正则表达式

Regex 全局匹配正则表达式,regex,perl,freeze,Regex,Perl,Freeze,我有以下perl代码: # $content is the text of a webpage while ($content =~ /rgRow.*?<td>(.*?)<\/td><td.*?>(.*?)<\/td><td.*?>(.*?)<\/td><td.*?>.*?<\/td><td.*?>(.*?)<\/td><td.*?><nobr>(.*?

我有以下perl代码:

# $content is the text of a webpage
while ($content =~ /rgRow.*?<td>(.*?)<\/td><td.*?>(.*?)<\/td><td.*?>(.*?)<\/td><td.*?>.*?<\/td><td.*?>(.*?)<\/td><td.*?><nobr>(.*?)<\/nobr><\/td>/sg) {
   # do stuff
}
我试着用下面这句话来看看它是怎么回事:

while ($content =~ m/rgRow.+?<td>(.+?)<\/td><td>(.+?)<\/td><td>(.+?)<\/td><td>(.+?)<\/td><td>(.+?)<\/td><td>(.+?)<\/td>/gs)
while($content=~m/rgRow.+?(.+?)(.+?)(.+?)(.+?)(.+?)(.+?)(.+?)(.+?)/gs)

原始代码不是我的。

我把这个问题看作是调试旧代码的问题。(不过,请参见末尾的解析器示例。)

报告的问题是正则表达式挂起。对我来说,它在几场比赛后退出,在第一线。我的第一个怀疑是一条松散的新线
/s
修饰符仅使
匹配新行。另一个嫌疑犯是明确匹配的
rgRow
短语——它也是
标记中的一个属性,在
*
下也是匹配的——冲突?最后,正则表达式显式地查找每个单元格,同时也使用
/g
修饰符。作为参考,这是正则表达式,在带有
/sg
修饰符的代码中使用

$patt = qr/rgRow.*? 
    <td>   (.*?)<\/td>
    <td.*?>(.*?)<\/td> 
    <td.*?>(.*?)<\/td> 
    <td.*?> .*? <\/td> 
    <td.*?>(.*?)<\/td> 
    <td.*?> <nobr>(.*?)<\/nobr> <\/td>
/x; 
$patt=qr/rgRow.*?
(.*?)
(.*?) 
(.*?) 
.*?  
(.*?) 
(.*?) 
/x;
一个字符一个字符地挑拣源字符是不愉快的,而且通常也不起作用。我们可以执行以下操作:删除新行,然后将
标记的内容捕获到数组中。正则表达式中所述的目的正是为了实现这一点。(我更改regex分隔符以避免编辑器着色。)

使用警告;
严格使用;
我的$msg='从url中提取'U';
(my$msg\u nonl=$msg)=~s%\n%%g;
my@raw_cells=$msg_nonl=~|(.*)| g;
#一旦我们做到了这一点:剥离、删除空元素
@cells=grep{!/^\s*$/}map{s%|%%g;$|}@raw_cells;
#也可以获取链接(“查看文档”)
@content=grep{!/是

不要总是依赖于
*?
,而是尽量明确你不想匹配的内容。在这种情况下,这很简单:你匹配的TD从不包含其他标记,因此你可以使用
[^]*
来捕获它们的内容。事实上,你应该在当前使用
*?
的任何地方都使用它

在下面的正则表达式中,我还将NOBR标记设置为可选的,并对其进行了扩展以匹配整个开头的TR标记,这更多是为了可读性

while ($content =~ 
  m!<tr\s+class="rgRow[^<>]*>\s*
    <td[^<>]*>([^<>]*)</td>
    <td[^<>]*>([^<>]*)</td>
    <td[^<>]*>([^<>]*)</td>
    <td[^<>]*>[^<>]*</td>
    <td[^<>]*>([^<>]*)</td>
    <td[^<>]*>(?:<nobr>)?([^<>]*)(?:</nobr>)?</td>
  !sxg) {
    # do stuff
}
while($content=~

m!请显示您正试图解析的HTML。无论如何,regex不是解析HTML的正确工具,为什么不使用HTML解析器呢?小结:不要使用regex解析HTML/XML,请使用适当的解析器。同意上面的说法,但如果您这一次需要这样做,那么使用
qr
打破这种讨厌的排列方式如何?这样做会容易得多看看。我更喜欢一些关于上面的正则表达式如何可能会导致“灾难性回溯”的答案/评论。至于我,我看不清楚它到底在做什么。至于我的评论,它是有建设性的:如果通过
qr
分解它,就更容易看到它的结构,然后可能会注意到它可以在哪里但是,出于善意(请不要冒犯):我对
HTML::TableExtract;
有很好的经验。
use warnings;
use strict;

my $msg = 'pulled_from_url';
(my $msg_nonl = $msg) =~ s%\n%%g;

my @raw_cells = $msg_nonl =~ |<td.*?>(.*?)<\/td>|g;

# Once we are at it: strip <nobr>, &nbsp;, drop empty elements
@cells = grep { !/^\s*$/ } map {  s%<\/?nobr>|&nbsp;%%g; $_ } @raw_cells;
# Get links ("View Document") out as well
@content = grep  {  !/<a.*?\/a>/ } @cells;
print "Total of " . scalar(@raw_cells) . " cells. ";
print "Cleaned up, down to " . scalar(@content) . " cells.\n";
print "$_\n" for @content;
Total of 280 cells. Cleaned up, down to 82 cells. CONSIDERATION OF REPORTS SUBMITTED BY ... DUE IN 1974 / MOROCCO State party's report ... 21 Feb 1974 ... True CONSIDERATION OF REPORTS SUBMITTED BY ... DUE IN 1972 / MOROCCO State party's report ... 17 Jan 1972 ... True
use HTML::TableExtract;   
my $te = HTML::TableExtract->new( keep_html => 1 );
$te->parse( "<table> " . $msg . "</table>" );
# We have one table, use top-level 'rows()' shorthand method
foreach my $row ($te->rows) {
    print join(',', @$row), "\n";
}
while ($content =~ 
  m!<tr\s+class="rgRow[^<>]*>\s*
    <td[^<>]*>([^<>]*)</td>
    <td[^<>]*>([^<>]*)</td>
    <td[^<>]*>([^<>]*)</td>
    <td[^<>]*>[^<>]*</td>
    <td[^<>]*>([^<>]*)</td>
    <td[^<>]*>(?:<nobr>)?([^<>]*)(?:</nobr>)?</td>
  !sxg) {
    # do stuff
}