0

<li>HTML ファイルがあり、と</li>タグの間のテキストを抽出したいと考えています。もちろん、これを行うには無数の方法がありますが、単純なシェル コマンドでこれを行う習慣を身につけると便利だと思いました。

awk '/<li[^>]+><a[^>]+>([^>]+)<\/a>/m' cities.html

問題は、これはすべてを印刷することですが、私は単純に括弧内に一致を印刷したいのですが([^>]+)、 awk がこれをサポートしていないか、私が無能です。後者の可能性が高いようです。提供された正規表現をファイルに適用し、指定された一致のみを抽出したい場合、どのようにしますか? awk私はすでに他の方法を半ダース知っていますが、このラウンドに勝たせる気がしません;)

編集: データは適切に構造化されていないため、位置一致 ( $1, $2, etc.) を使用することはできません。

4

5 に答える 5

2

リストタグに正当な HTML マークアップを含めることができる一般的なケースでこれを行う場合awkは、間違ったツールです。この仕事に適したツールは HTML パーサーです。HTML パーサーは、HTML の亜種や不正な形式の HTML など、HTML 構文解析の細部をすべて正確に取得できると信頼できます。

HTML フォーマットを制御できる特殊なケースでこれを行っている場合は、awk作業を行うことができる場合があります。たとえば、各リスト要素が複数の行を占めることはなく、常に</li>同じ行で終了し、マークアップ (リストを含むリストなど) を決して含まないことを保証できると仮定して、awkこれを行うために を使用できます。 、しかしawk、最初にリスト要素を含む行を見つけてから、他のawkコマンドを使用して興味のある部分文字列だけを見つけるプログラム全体を書く必要があります.

しかし、一般的に、awkこの仕事には不適切なツールです。

于 2009-06-12T02:07:39.257 に答える
1
gawk -F'<li>' -v RS='</li>' 'RT{print $NF}' file

私にとってはかなりうまくいきました。

于 2010-07-13T16:54:16.723 に答える
0

awk についてはよくわかりません。代わりに Perl はどうでしょうか。

tr -d '\012' the.html | perl \
-e '$text = <>;' -e 'while ( length( $text) > 0)' \
-e '{ $text =~ /<li>(.*?)<\/li>(.*)/; $target = $1; $text = $2; print "$target\n" }'

1)ファイルから改行を削除し、perlを介してパイプします

2)完全なテキストで変数を初期化し、テキストがなくなるまでループを開始します

3) リスト項目タグで区切られたものに対して「貪欲でない」一致を行い、ターゲットを保存して印刷し、次のパスに備えます

わかる?(警告、このコードを自分で試していません。すぐに家に帰る必要があります...)

PS - "perl -n" は Awk (nawk?) モードです。Perl は主に Awk のスーパーセットなので、わざわざ Awk を学ぼうとはしませんでした。

于 2009-06-12T02:28:15.743 に答える
0

私が見るいくつかの問題があります:

  • パターンには、Perl での複数行の一致に重要な末尾の 'm' がありますが、Awk は Perl 互換の正規表現を使用しません。(少なくとも、標準の (非 GNU) awk はそうではありません。)
  • それを無視すると、パターンは、終了リスト項目ではなく、 「開始リスト項目」の後に「 <a>」へのアンカー「 」を検索するようです。</a>
  • >アンカーの本体として' ' 以外のものを検索します。それは自動的に間違っているわけではありませんが、' <' でないもの、またはどちらでもないものを検索する方が一般的かもしれません。
  • Awk は複数行の検索を行いません。
  • Awk では、' $1' は最初のフィールドを示し、フィールドはフィールド区切り文字 (デフォルトでは空白) で区切られます。
  • クラシックnawkでは (' sed & awk' book vintage 1991 に記載されているように)、マッチからサブフィールドを引き出すためのメカニズムがありません。

Awk がこの仕事に適したツールであるかどうかは明らかではありません。実際、正規表現がこの仕事に適したツールであるかどうかは完全には明らかではありません。

于 2009-06-12T02:00:08.557 に答える
0

あなたのスクリプトで、あなたが望むものを得ることができれば(それはタグが1行にあることを意味<li><a>ます);

$ cat test.html | awk 'sub(/<li[^>]*><a[^>]*>/,"")&&sub(/<\/a>.*/,"")'

また

$ cat test.html | gawk '/<li[^>]*><a[^>]*>(.*?)<\/a>.*/&&$0=gensub(/<li[^>]*><a[^>]*>(.*?)<\/a>.*/,"\\1", 1)'

1 つはすべての awk 用で、2 番目は gnu awk 用です。

于 2009-06-12T16:17:57.420 に答える