处理perl

时间:2018-01-31 02:32:08

标签: regex perl curl

我正在处理curl -s的输出。 具体来自此页面:https://support.microsoft.com/en-us/help/971058/how-do-i-reset-windows-update-components

在我陈述目标之前,我会提到我只对那些从本页面的卷曲输出中提取所需数据的答案感兴趣。 (我知道此页面上建议的操作已经可以作为文本,PowerShell脚本等提供。)

最终目标是获取dll列表。它快速做到没有任何大惊小怪(所以一个单行),但它现在成为我的学习经验。基本正则表达式是/regsvr32.exe (.*?\.dll)/

我感兴趣的卷曲输出看起来像这样(注意缺少换行符):

<li>regsvr32.exe a.dll</li><li>regsvr32.exe b.dll</li>

所以我尝试了如下perl: perl -F"li" -lane 'print $1 if /regsvr32.exe (.*?\.dll)/g'

(逻辑是我可以在任何“li”的情况下轻松分裂,并且仍然应该得到合理的结果,我可以稍后进行微调)

我无法让-F完全工作。我尝试了单个字符,我尝试了像/ PATTERN /这样的正则表达式,我尝试省略了各种其他标志(特别是-l),我写了一个单行来显示分裂。我无法分裂发生。

然后我检查了卷曲手册页,看看它是否有任何可能有帮助的输出消毒剂。这是一个looong手册页,但我没有看到任何东西。

然后我发现,如果我写的perl工作不管相同的正则表达式是否在同一行上多次匹配,那就太好了。但我找不到任何合理的单线班车。

我能找到能够产生所需输出作为单线的最佳方法是:

curl -vs \
https://support.microsoft.com/en-us/help/971058/how-do-i-reset-windows-update-components 2>&1 | \
perl -pe 's|</li>|\n|g' | \
perl -lne 'print $1 if /regsvr32.exe (.*?\.dll)/'

有人可以建议不那么荒谬的东西吗?

另外,我喜欢Perl的-F论证的任何解释,比perldoc perlrun更具启发性。

2 个答案:

答案 0 :(得分:3)

无需拆分<li>元素或使用解析器(您不必关心文档的结构),因此您只需搜索regsvr32.exe字符串即可到下一个<字符。

curl $msft_url | perl -lane 'print for ( m|regsvr32.exe (.+?.dll)<|g );'

要处理多个捕获,您需要额外的while循环来迭代匹配对。 shift命令从数组中提取第一个元素,reverse命令反转数组。这将捕获2个字符串并以相反的顺序打印它们:

curl $msft_url | perl -lane '@m = m|(regsvr32).exe (.+?.dll)<|g; while (@m) { print join " ", reverse(shift @m, shift @m) };'

答案 1 :(得分:1)

我已经发现了如何做我正在尝试的其他方法(有点),这是让perl做分裂。关键是-a-F不确定记录拆分行为。只有-0可以。

-a每个记录(内部)拆分为@F数组,文档现在似乎完全清除。 @F数组主要用于awk样式,以便人们可以很容易地说出#34;打印第二列&#34; ($F[1])。所以我可以改写为&#34; -0通常是如何获取行的,-a通常是如何获取列,粗略地说。&#34;

然而,它可以达到目的:

curl -vs \
https://support.microsoft.com/en-us/help/971058/how-do-i-reset-windows-update-components 2>&1 \
| perl -F'<\/li>' -lane 'foreach my $match (map { /regsvr32.exe (.+?.dll)/ } @F) {print"$match"}

由于显而易见的原因,我更喜欢这个问题的公认解决方案,但我可以看到这种方法在其他地方很方便。 PS - -0解决方案(使用>上的记录拆分)是:

| perl -0x3c -ne 'print "$1\n" if /regsvr32.exe (.+?\.dll)/'