1

首先,让我这样说:
我知道 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”和“DESPiTE”
我错过了什么?

4

3 回答 3

1

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.

于 2012-10-17T10:00:53.183 回答
1

这可能对您有用(GNU sed):

sed -n '/[\x00\x01\x02]/q1;/hebrew/!b;s//\x01/;/DESPiTE/!b;s//\x02/;/downloadsubtitle.php?id=/!b;s//\x00/;s/.*\x00\([0-9]\+\)[^\x00\x01\x02]*\x01[^\x00\x01\x02]*\x02.*/\1/p' file

解释:

  • /[\x00\x01\x02]/q1检查该行是否包含分隔符,如果是,则使用错误代码中止1
  • /hebrew/!b;s//\x01/检查行是否包含hebrew,如果不是 bail out,如果是,则将单词hebrew转换为单个字符\x01
  • /DESPiTE/!b;s//\x02/检查行是否包含DESPiTE,如果不是 bail out,如果是,则将单词DESPiTE转换为单个字符\x02
  • /downloadsubtitle.php?id=/!b;s//\x00/检查行是否包含downloadsubtitle.php?id=,如果不是 bail out,如果是,则将单词downloadsubtitle.php?id=转换为单个字符\x00
  • s/.*\x00\([0-9]\+\)[^\x00\x01\x02]*\x01[^\x00\x01\x02]*\x02.*/\1/p打印出所需的号码。
于 2012-10-17T13:13:45.663 回答
0

问题是*一个贪婪的运算符,所以它会尽可能多地匹配,导致它不是在第一个可能的匹配上停止,而是在最后一个可能的匹配上停止。因此,您可能应该更改它尝试匹配的内容。问题是您希望它匹配除另一个“downloadsubtitle.php?id=”之外的任何内容,这在sed. 您可以创建一个更复杂的 sed 脚本,也可以使用一个简单的解决方法,假设?链接和标题之间没有任何 s =)

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,模式空间的第一行是我们要搜索文本的地方。因此,我们使用搜索表达式,从缓冲区的开头开始搜索字符串hebrewDESPiTE并且这些字符串没有相互分隔,也没有从缓冲区的开头用换行符分隔。因此,我们只搜索了第一行。

如果找到匹配项,我们使用g从保留空间中获取 ID,p打印它,然后q退出。

如果我们没有找到匹配项,我们只需跳回loop标签,并搜索下一个出现。跳转前的条件是防止死循环。如果没有什么可搜索的,它就会退出。

希望这会有所帮助=)

于 2012-10-17T11:51:56.820 回答