首先,让我这样说:
我知道regx'ing html被认为是一种糟糕的方法,但如果chuck norris可以,为什么我不能?;)
我想解析此html页面:http://pastebin.com/unAifctF
基于三个参数。我试过了:(谢谢pixellany)
sed -n '/hebrew/{/DESPiTE/s/downloadsubtitle.php?id=/XXX/1};s/.*XXX([0-9]*).*/1/p'
它返回228344而不是228338
,我尝试了:(谢谢doubleDown)
sed -nr 's/.*downloadsubtitle.php?id=([0-9]+).*hebrew.*DESPiTE.*/1/p'
返回228343而不是228338预期的结果是228338,因为它是第一个数字,前面是"downloadsubtitle.php \?id \=",后面是"hebrew"one_answers"DESPiTE">
我缺少什么?
这可能对你有用(GNU sed):
sed -n '/[x00x01x02]/q1;/hebrew/!b;s//x01/;/DESPiTE/!b;s//x02/;/downloadsubtitle.php?id=/!b;s//x00/;s/.*x00([0-9]+)[^x00x01x02]*x01[^x00x01x02]*x02.*/1/p' file
说明:
/[x00x01x02]/q1
检查行是否包含分隔符,如果是,则中止并返回错误代码1
/hebrew/!b;s//x01/
检查行是否包含hebrew
,如果不退出,则将单词hebrew
翻译为单个字符x01
/DESPiTE/!b;s//x02/
检查行是否包含DESPiTE
,如果不退出,则将单词DESPiTE
翻译为单个字符x02
/downloadsubtitle.php?id=/!b;s//x00/
检查行中是否包含downloadsubtitle.php?id=
,如果未退出,则将单词downloadsubtitle.php?id=
翻译为单个字符x00
s/.*x00([0-9]+)[^x00x01x02]*x01[^x00x01x02]*x02.*/1/p
打印出所需的数字
Perl解决方案:
perl -nE '
@fields = split /downloadsubtitle.php?id=([0-9]+)/;
for (1 .. $#fields) {
next unless $_ % 2;
say $fields[$_] if $fields[$_ + 1] =~ /hebrew.*DESPiTE/;
}
' unAifctF.html
它是如何工作的?它在downloadsubtitle.php?id=XXX
上分割一行,同时将数字保持在中间。然后,它打印一个数字,如果它后面的字符串直到下一个downloadsubtitle...
包含hebrew
和DESPiTE
。
问题是*
是一个贪婪运算符,因此它会尽可能多地匹配,导致它不是在第一个可能的匹配上停止,而是在最后一个可能的匹配对停止。因此,您可能应该更改它试图匹配的内容。问题是,您希望它匹配除另一个"downloadsubtitle.php?id="之外的任何内容,这在sed
中很困难。您可以创建一个更复杂的sed脚本,也可以使用一个简单的解决方法,假设链接和title之间不会有任何?
=)
sed -nr 's/.*downloadsubtitle.php?id=([0-9]+)[^?]*hebrew[^?]*DESPiTE.*/1/p'
如果你想要一个合适的脚本:
#!/bin/sed -nf
: next
$! { N; b next }
s/n//g
s/downloadsubtitle.php?id=([0-9][0-9]*)/
1/
: loop
s/^[^n]*n//
h
s/([0-9]*).*/1/
x
s/downloadsubtitle.php?id=([0-9][0-9]*)/
1/
/^[^n]*hebrew[^n]*DESPiTE/ { g; p; q }
/^[0-9]*/ b loop
这个脚本首先将整个文件加载到模式空间(即工作缓冲区)。它在前两行中这样做。第一行用:
"命令"声明一个名为next
的标签。第二行使用N
命令将输入的下一行附加到模式空间中,然后跳回next
标签,但只有当我们还没有读取最后一行时,才会执行这两个命令。第三行删除所有换行符。
现在,我们将第一次出现的downloadsubtitle.php?id=[0-9][0-9]*
替换为换行符(由后面跟着实际换行的反斜杠表示)和ID号。
创建了一个新标签loop
,在它之后我们要做的第一件事就是删除第一个换行符之前的所有内容(所以我们删除了id之前的所有东西)。
现在我们有了一系列命令,这些命令将提取数字并将其存储到保持空间(一个辅助缓冲区)中。我们首先使用h
命令将整个模式空间复制到保持空间中,然后删除数字之后的所有内容,然后用x
交换保持和模式空间的内容。现在,保留空间包含数字,模式空间已恢复为其值。
为了防止贪婪搜索,我们将在downloadsubtitle.php?id=[0-9][0-9]*
的下一次出现之前放置一个换行符。我们也可以只留下ID号,因为换行符将指示我们找到了字符串的其余部分。
现在是搜索部分。概括一下,我们在保持空间中有实际的ID,模式空间的第一行是我们想要搜索文本的地方。因此,我们使用搜索表达式,从缓冲区的开始搜索字符串hebrew
和DESPiTE
,它们彼此之间或缓冲区的开头没有换行符。因此,我们只搜索了第一行。
如果找到匹配,我们使用g
从保留空间获取ID,使用p
打印ID,然后使用q
退出。
如果找不到匹配项,我们只需跳回loop
标签,然后搜索下一个匹配项。跳转之前的条件是防止出现无限循环。如果没有什么可搜索的,它就会退出。
希望这有帮助=)