• ベストアンサー

対応するタグに囲まれた部分を抜き出すプログラム

与えられた文字列から、対応するタグに囲まれた部分文字列を順次抜き出していく簡潔なプログラムの書き方を探しています。 例えば、注目するタグが <b> と </b> の場合、文字列 "<b>word1</b> word2 <b>word3 word4</b>" が与えられたとき、部分文字列 "word1"、"word3 word4" を順次抜き出すようなプログラムで、特に簡潔な考え方で書かれたものに関心があります。 ただ、"<b><b>word1</b> word2 <b>word3 word4</b></b>" のように、部分文字列が他の部分文字列に埋め込まれた形を含む場合には、例えば、"word1", "word3 word4", "word1 word2 word3 word4" のように、文字列左端の方からタグを含まない部分文字列を抜きだすようなプログラムは簡潔に書けないものでしょうか? 例えば以下のようにすれば文字列右端の方から処理できると思うのですが、このような感じで、文字列左端の方から処理していくプログラムというのは書けないものかと思いました。 while($input=~s/(.*)<b>(.*?)<\/b>/$1$2/) {   print "$2\n" } よろしくお願いいたします。

  • Perl
  • 回答数3
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
  • leaz024
  • ベストアンサー率75% (398/526)
回答No.3

while ($input =~ s/<b>((?:(?!<b>).)*?)<\/b>/$1/) {   print "$1\n"; } という感じでどうでしょう? 記述を簡素化するため、マッチした <b> 及び </b> は削除していますので、元の文字列が必要な場合は予め退避しておいて下さい。

bender
質問者

お礼

回答ありがとうございます。 このような書き方ができるのですね! 期待した出力を得られたうえに、今後の勉強にもなりました。 ありがとうございました。

その他の回答 (2)

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

HTMLの解析というより、対応するタグに囲まれた部分文字列を順次抜き出していくというのであれば、 Perl5.8の標準モジュールText::Balancedを使うといいと思います。 perldoc Text::Balanced して貰えばいいと思いますが、なかなかわかりにくいと思うので、 サンプルを作ってみました。 --------------------------------------------------------------- use Text::Balanced qw(extract_bracketed extract_tagged); $data="<b><b>word1</b> word2 <b>word3 word4</b></b>"; &extract($data); sub extract($){ my $text = shift; my ($match,$rest,$prefix,$start,$content,$end); while(($match,$rest,$prefix,$start,$content,$end)=extract_tagged($text, '<b>', '</b>','[^<]*')){ last if $match eq ""; #マッチしなくなった &extract($content); #ネストの処置 $content =~ s/<\/?b>//g; #表示用にタグ削除 print "$content\n"; $text=$rest; #残りのマッチをさせる準備 } } ---------------------------------------------------------------- サンプルでは、printしてますけど、必要なら配列にpushすればいいと思います。 また、extract_bracketedで対になるカッコへのマッチングを扱えます。(日本語の「」を扱うためにはextract_taggedの方が良いかも知れません) あと、用途によって、同類の関数が他にも含まれています。

bender
質問者

お礼

回答、それに丁寧な例と説明まで書いていただいてありがとうございます。 Text::Balanced という便利なものがあるのですね。いつも回答を参考にさせていただいているのですが、今回も参考になりました。 ありがとうございました。

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.1

HTML::Parserや、HTML::TreeBuilderを使って、HTMLの構造解析を行った上で、情報抽出してみては。

bender
質問者

お礼

アドバイスありがとうございます。 タグの種類が少ない場合(例えば、<b>と</b>だけのとき)、ごく簡潔な正規表現で用が足りるのではないかと考えたのですが、よい考えが浮かびませんでした。 <b>...</b>に限らず、例えば、(...)や「...」の場合についての方法に関心があるのですが、<b>...</b>の場合の方が、より一般的な形の回答をいただけるかと思いそのように質問してしました。 いずれにしても、アドバイス大変ありがとうございました。

関連するQ&A

  • 「すべてのプログラム」と「検索」が変?

    WindowsXP/HE/SP2で運用してますが、スタートから「すべてのプログラム」を表示すると、プログラム名が縦に3列並び、4列目はアイコンと字が1字しか見えません。(右端) 画面の左端は、丁度1列分くらい空いていて、最近使ったソフト名などが出ていますが、これは私には不要なので、プログラムをこの部分まで左に寄せたいのですが、方法が分かりません。 同じくスタートから「検索」をすると、「検索が完了しましたが、何も見つかりませんでした。」などという文字列の上半分が、「名前」や「フォルダ名」などのバーの下に隠れて見えません。 以上2つの対処方法を教えて下さい。

  • マーキーのタグについて

    横長の画像をスクロールさせたいのですが、普通にマーキーを使うと、 右端の方から少しずつ出てくるので長い画像を全部見るのに時間がかかります。 例えば、右側から画像が出て左に流れていくとして、画面の左端に、 すでに画像の左端があり、どんどん左に流れていくようにするには どんなタグを使えばよいのでしょうか。 よろしくお願いいたします。

  • OpenOffice3.3.0のCalcの並び替え

    10000000c 20000000b 10000000a という文字列がある時、並び替えをすると左端の文字から並び替えることができますが、右端の文字列から並び替えることはできますか? 10000000a 20000000b 10000000c こういうふうにしたいのですが。

  • 背景色と画像を同時にのせる

    背景画像を壁紙にし、その画像の上に文字を書きたいのですが、 画像と文字が入り混じって文字が見にくくなってしまいます。 そこで、画像は左右の端だけ残して(左右端合計で画像の幅が画面の40%くらいになるように)、 真ん中の60%くらいに、画像を張る前の白い状態にしたいと思うのですが、HTMLのタグがわかりませんorz タグを教えてほしいです。 よろしくお願いします。 ---------------------------- (画像左端{20%}) (何もない白い背景{60%}) (画像右端{20%}) (画像左端) (何もない白い背景) (画像右端) (画像左端) (何もない白い背景) (画像右端) (画像左端) (何もない白い背景) (画像右端) (画像左端) (何もない白い背景) (画像右端) (画像左端) (何もない白い背景) (画像右端) (画像左端) (何もない白い背景) (画像右端) (画像左端) (何もない白い背景) (画像右端) ↑こんな感じです

  • ヤフオクで抹消線タグ

    ヤフオクでのことです。 オークションテンプレート(スキン)を利用し、出品しています。 <br>、<font color="色">文字</font>、<b></b>、などを使用して、 出来る限り見やすいようにしていますが、 抹消線タグを何度試みてもダメなようでした。 <S> 文字列 </S> 及び <STRIKE> 文字列 </STRIKE> どちらも。 同じように試みた方、ダメでしたでしょうか? やはり、抹消線タグはヤフオクの場合使用できないのでしょうか?

  • HTMLタグの中味抽出

    HTMLのタグの中味を抽出する正規表現として、以下の形を学びました。 [^<]+?(?=>) この正規表現で以下のHTML文を処理すると、 <tag_nakami_1><tag_nakami_2>title_text</tag_nakami_1></tag_nakami_2> 以下の結果が出ました。 tag_nakami_1 tag_nakami_2 /tag_nakami_1 /tag_nakami_2 ですが、なぜ、「title_text」の部分がうまく取り除かれたのかがわかりません。 <tag_nakami_1><tag_nakami_2> まで処理がすんで、次は title_text</tag_nakami_1> が処理対象の文字列となるのでは無いでしょうか?その場合、末尾の > より前の部分、title_text</tag_nakami_1 から < のみが除かれた文字列、title_text/tag_nakami_1 が抽出される、つまり以下のような結果が出そうに思えます。 tag_nakami_1 tag_nakami_2 title_text/tag_nakami_1 /tag_nakami_2 ですが実際はそうなりません。 これはなぜなのでしょうか……。

  • word2007の段落配置について、2つ質問があります。

    word2007の段落配置について、2つ質問があります。 (1)中央揃えとはなんですか?例えば、1行40字文字が入力できる場合、1行に10字入力されていれば、その文字は16行~25行に配置され、左端~文字の左端,右端~文字の右端までの空白が同じになるってことですか? (2)両端揃えとはなんですか?各行の文字列が段落の両端に揃うように調整される配置という解説がありますが、いまいちぱっとしません。 それと、両端揃え前と後の画像をUPしてくだされば幸いです。

  • vbaプログラムで分かりません。

    excelのsheet2のA列には1または2または5が入っていて、B列には00542,00984などたくさんの文字列が入っています。 それでA列の数字が2かつB列が2文字目降(054,098)の3文字分が098または099なら、sheet3のA列に0を出力というプログラムを作っています。 どうやったら良いか分かりません。 分かる方、教えてください。 2文字目以降というのが分かりません。

  • プログラム実行中にプログラムを書き換えるには?

    実行中のプログラムの中でそのプログラムの一部を書き換えて保存するにはどうすればいいですか? 例えば次のようなプログラムの場合、このプログラムの中でTEXT("最初の文字列");の部分の文字列を別な文字列に変更しプログラムを更新したいです。 (プログラム終了後にもう一度実行すると「moji[20]=」の部分は前回実行時に書き換えた文字列が代入されているようにしたい) #include<windows.h> int WINAPI WinMain(HINSTANCE hinst,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int ncmdshow){ TCHAR moji[20]=TEXT("最初の文字列"); MessageBox(NULL,moji,TEXT("文字列表示"),MB_OK); return 0; } --- 実行環境 --- Microsoft Visual C++ 2010 Express WIN32 ユニコードビルド C言語

  • 他のプログラムとのデータ転送

    A、Bという二つのプログラムがあるとします。 Aで入力してもらったデータをBへ送り、Bでその受け取ったデータの処理し、処理したデータをAへ送り返し、Aでその処理したデータを表示させるというプログラムを作ろうとしているところです。 このデータというのは、文字列で構いません。 行う処理は簡単なものなので自力でできますが、どのようにして他のプログラムにデータを受け渡せばよいのか分かりかねます。 どなたかご存じの方がいらっしゃいましたら、ご教授願います。 よろしくお願いします。 ↓(入力) A    →(データ)→    B A ←(処理後のデータ)← B ↓(出力) イメージは、こんな感じです。

    • ベストアンサー
    • Perl

専門家に質問してみよう