标签:html c regex html-parsing
我在这里偶然发现了一些挑战:如何在正则表达式的帮助下获取HTML表格的内容.让我们说这是我们的表:
<table someprop=2 id="the_table" otherprop="val">
<tr>
<td>First row, first cell</td>
<td>Second cell</td>
</tr>
<tr>
<td>Second row</td>
<td>...</td>
</tr>
<tr>
<td>Another row, first cell</td>
<td>Last cell</td>
</tr>
</table>
我已经找到了一个有效的方法,但是涉及到多个正则表达式的执行步骤:
>获取正确的表并将其行放在后引用1中(文档中可能有多个行):
<表[^>]?* ID = “the_table”[^>]?*>(?*)< /表>
>获取表格的行并将单元格放在后面引用1中:
< TR * GT;?<(*); / TR>
>最后在反向引用1中获取单元格内容:
< TD * GT;?(?*)< / TD>
现在这一切都很好,但是使用一个花哨的正则表达式来完成这一切将会更加令人敬畏……有人知道这是否可行?
解决方法:
确实没有可能的正则表达式解决方案适用于任意数量的表数据,并将每个单元格放入单独的后向引用中.这是因为通过反向引用,您需要为要创建的每个backref创建一个独特的开放式窗口,并且您不知道自己有多少个单元格.
使用一种或另一种循环来提取数据没有任何问题.例如,在最后一个,在Perl中,这将是这个,因为$tr已经包含你需要的行:
@td = ( $tr =~ m{<td.*?>(.*?)</td>}sg );
现在$td [0]将包含第一个< td>,$td [1]将包含第二个,等等.如果你想要一个二维数组,你可以将它包装在这样的循环中以填充新的@cells变量:
our $table; # assume has full table in it
my @cells;
while(my($tr) =~ $table = m{<tr.*?>(.*?)</tr>}sg) {
push @cells, [ $tr =~ m{<td.*?>(.*?)</td>}sg ];
}
现在你可以进行二维寻址,允许$cells [0] [0]等.外部显式循环一次处理一行,内部隐式循环拉出所有单元格.
这将适用于您展示的固定样本数据.如果这对你来说足够好,那就太好了.使用它并继续前进.
什么可能是错的?
但是,关于数据内容的模式实际上有很多假设,我不知道你知道的.首先,请注意我是如何使用/ s以便它不会卡在换行符上的.
但主要问题是最小匹配并不总是你想要的.至少,不是一般情况.有时它们并不像你想象的那么小,匹配的比你想要的多,有时它们只是不够匹配.
例如,像< i>(.*?)< / i>的模式.如果字符串是:将获得比你想要的更多:
<i>foo<i>bar</i>ness</i>
因为您最终会匹配字符串< i> foo< i> bar< / i>.
另一个常见问题(不包括不常见的问题)是像< tag.*?>这样的模式.可能匹配得太少,比如
<img alt=">more" src="somewhere">
现在,如果您使用简单的< img.*?>在那,你只会捕获< img alt =“>,这当然是错误的.
我认为最后一个主要问题是你必须完全忽略解析中的某些事情.这个嵌入式注释的最简单的演示(也是< script>,< style>和CDATA`),因为你可以有类似的东西
<i> some <!-- secret</i> --> stuff </i>
这会甩掉像< i>(.*?)< / i>这样的东西.
当然,有很多方法可以解决这些问题.一旦你这样做了,这真的是相当多的努力,你会发现你已经构建了一个真正的解析器,完全有很多辅助逻辑,而不仅仅是一个模式.
即便如此,您只处理格式良好的输入字符串.错误恢复和轻柔失败是一种完全不同的艺术.
标签:html,c,regex,html-parsing 来源: https://codeday.me/bug/20190903/1794737.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。