1

まず、これを言わせてください。
正規表現のhtmlは悪いアプローチと見なされていることは知っていますが、チャック・ノリスができるのなら、なぜできないのでしょうか。;)
このhtmlページを解析したい:http://pastebin.com/unAifctF3
つのパラメーターに基づいています。私が試した:(ありがとうpixellany)

sed -n  '/hebrew/{/DESPiTE/s/downloadsubtitle.php?id=/XXX/1};s/.*XXX\([0-9]*\).*/\1/p'  

これは228338の代わりに228344を返し
、私は試しました:(ありがとうdoubleDown)

sed -nr 's/.*downloadsubtitle.php\?id\=([0-9]+).*hebrew.*DESPiTE.*/\1/p'  

これは、228338ではなく228343を返します。これは、最初の数値の前に「downloadsubtitle.php \?id \ =」が続き、その後に「hebrew」と「DESPiTE」が続くため、期待される結果は228338
です。

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行にベイルアウトが含まれていないかどうかを確認し、含まれている場合は単語hebrewを1文字に翻訳します\x01
  • /DESPiTE/!b;s//\x02/DESPiTE行にベイルアウトが含まれていないかどうかを確認し、含まれている場合は単語DESPiTEを1文字に翻訳します\x02
  • /downloadsubtitle.php?id=/!b;s//\x00/downloadsubtitle.php?id=行にベイルアウトが含まれていないかどうかを確認し、含まれている場合は単語downloadsubtitle.php?id=を1文字に翻訳します\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

このスクリプトは、ファイル全体をパターンスペース(つまり、作業バッファー)にロードすることから始まります。これは最初の2行で行われます。next最初の行は、:「コマンド」で呼び出されるラベルを宣言しています。2行目は、コマンドを使用して入力からパターンスペースへの次の行を追加しN、ラベルに戻りnextますが、これら2つのコマンドは、最後の行をまだ読んでいない場合にのみ実行されます。3行目では、すべての改行文字が削除されます。

ここで、の最初の出現箇所を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それを印刷してqから終了するために使用します。

一致するものが見つからない場合は、loopラベルに戻って次の出現箇所を検索します。ジャンプする前の条件は、無限ループを防ぐことです。検索するものがない場合は終了します。

これがお役に立てば幸いです=)

于 2012-10-17T11:51:56.820 に答える