确实没有可能的正则表达式解决方案适用于任意数量的表数据,并将每个单元格放入单独的后向引用中.这是因为通过反向引用,您需要为要创建的每个backref创建一个独特的开放式窗口,并且您不知道自己有多少个单元格.
使用一种或另一种循环来提取数据没有任何问题.例如,在最后一个,在Perl中,这将是这个,因为$tr已经包含你需要的行:
@td = ( $tr =~ m{
(.*?)}sg );现在$td [0]将包含第一个< td>,$td [1]将包含第二个,等等.如果你想要一个二维数组,你可以将它包装在这样的循环中以填充新的@cells变量:
our $table; # assume has full table in it
my @cells;
while(my($tr) =~ $table = m{
(.*?)}sg) {push @cells, [ $tr =~ m{
(.*?)}sg ];}
现在你可以进行二维寻址,允许$cells [0] [0]等.外部显式循环一次处理一行,内部隐式循环拉出所有单元格.
这将适用于您展示的固定样本数据.如果这对你来说足够好,那就太好了.使用它并继续前进.
什么可能是错的?
但是,关于数据内容的模式实际上有很多假设,我不知道你知道的.首先,请注意我是如何使用/ s以便它不会卡在换行符上的.
但主要问题是最小匹配并不总是你想要的.至少,不是一般情况.有时它们并不像你想象的那么小,匹配的比你想要的多,有时它们只是不够匹配.
例如,像< i>(.*?)< / i>的模式.如果字符串是:将获得比你想要的更多:
foobarness
因为您最终会匹配字符串< i> foo< i> bar< / i>.
另一个常见问题(不包括不常见的问题)是像< tag.*?>这样的模式.可能匹配得太少,比如
现在,如果您使用简单的< img.*?>在那,你只会捕获< img alt =“>,这当然是错误的.
我认为最后一个主要问题是你必须完全忽略解析中的某些事情.这个嵌入式注释的最简单的演示(也是< script>,< style>和CDATA`),因为你可以有类似的东西
some stuff
这会甩掉像< i>(.*?)< / i>这样的东西.
当然,有很多方法可以解决这些问题.一旦你这样做了,这真的是相当多的努力,你会发现你已经构建了一个真正的解析器,完全有很多辅助逻辑,而不仅仅是一个模式.
即便如此,您只处理格式良好的输入字符串.错误恢复和轻柔失败是一种完全不同的艺术.