- ベストアンサー
正規表現について
Htmlのタグの属性を正規表現を用いて取得しようとしています。 たとえば <font size="2" face="MS 明朝"> の場合、 "2"と "MS 明朝" を取得したいのですが、 以下のように定義を "="から始まり、空白か">"迄と定義した所、 pattern = Pattern.compile("=(.*?)[ >]"); としてマッチングした所、 "2"と "MS がとれてしまいました。 "(ダブルクォーテーションの中の[ >](空白等)は判定しないような 定義に出来るのでしょうか。 宜しくお願いします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
あー説明文を一生懸命かいていたら自分で解決していましたか(^^; > (?<==) > は前方一致ですね。つまり=から始まるもの。 > 但し、=自体は検索結果に含まれないんですね。 意味はあっていますが、通常「戻り読み」 (look-behind)等と呼ばれます。 Pattern (Java Platform SE 6) http://java.sun.com/javase/ja/6/docs/ja/api/java/util/regex/Pattern.html だと「後読み」になってますね。 > (?= > は後方一致で これも、通常は「先読み」(look-ahead)と呼ばれます。 > (?: はグループ化で そうです。 単なる ( と )でもグループ化はできますが、 それとの違いは後方参照(back reference) ができるかどうかです。 (?: )によるグループは後方参照できません。 #その代わりちょっと高速 といったところです。 *? と * の違いは良いですよね?
その他の回答 (3)
- sakusaker7
- ベストアンサー率62% (800/1280)
一番問題がなさそうな条件を考えてみました。 何か問題点 or 疑問点があれば補足に書いてください。 この後数時間ばかしネットにアクセスできないのでよろしくおねがいします。 import java.lang.*; import java.util.regex.*; public class Moge { static public void main(String[] args) { //String target = "<font size=\"2\" face=\"MS 明朝\">"; String target = "<font size=2 face=MS 明朝 width=84 colspan=2 valign=top>"; Pattern p = Pattern.compile("(?<==).*?(?=(?: +[^ =>]+=)|>)"); Matcher m = p.matcher(target); while (m.find()) { System.out.println("found: " + m.group(0)); } } } found: 2 found: MS 明朝 found: 84 found: 2 found: top
お礼
すいません。勉強不足で 一段目の (?<==) は前方一致ですね。つまり=から始まるもの。 但し、=自体は検索結果に含まれないんですね。 なるほどです。勉強になります。 (?= は後方一致で (?: はグループ化で " +" は空白が一回以上連続して、その次が空白か=か>以外のものが1回以上 連続していて=で終わるもの。 つまり、空白の次の文字列の最後が=になっているものか">"が後方一致の判定ですね。 なるほどです。すごいです。 勉強になりました。 有難うございました。
補足
sakusaker7さん 本当に有難うございました。 無事結果を取得できました。 出来れば意味も把握しておきたく、色々調べてみましたが、 下記の意味がわかりませんでした。 (?<==).*?(?=(?: +[^ =>]+=)|>) とりあえず括弧で区切ってみました。 (?<==) .*? (?=(?: +[^ =>]+=)|>) 2段目の .*? はなんとか意味が分かるのですが、 1段目の (?<==) の意味が分かりません。 3段目も同様に?の意味が分かりません。 ?は前方の文字が0回か1回出現するという意味みたいですが、 今回はその使われ方じゃない気がします。 お手数をお掛けしますが、ご教授ください。 宜しくお願いします。
- sakusaker7
- ベストアンサー率62% (800/1280)
>今回WORDから自動生成されたHtmlを使用しているのですが、属性に'"'が付いてない場合があるようです。 なるほど。 ただ XHTMLでなくても > 属性値に英数字(a-z, A-Z, 0-9)、ハイフン(-)、 > ピリオド(.)、アンダースコア(_)、コロン(:) > 以外の文字を含むときは属性値をダブルクォーテーション(") > もしくはクォーテーション(')で囲まなくてはなりません。 http://www.tohoho-web.com/html/memo/attr.htm ということなので、 MS 明朝 というのはあまりにもナニですがまあ我慢するとして、 “MS 明朝”のように、間に入る空白はひとつだけ とか限定条件を置いて良いですか? =を含む文字列を属性の値としてクォートなしで 使う。なんて状況はちと考えたくないです。
- sakusaker7
- ベストアンサー率62% (800/1280)
> 以下のように定義を "="から始まり、空白か">"迄と定義した所、 なぜこのような定義に? =の後の、'"'で囲まれた部分というのでは 都合が悪いですか? import java.lang.*; import java.util.regex.*; public class Moge { static public void main(String[] args) { String target = "<font size=\"2\" face=\"MS 明朝\">"; Pattern p = Pattern.compile("(?<==)\"[^\"]+\""); Matcher m = p.matcher(target); while (m.find()) { System.out.println("found: " + m.group(0)); } } } 実行結果: found: "2" found: "MS 明朝" > "(ダブルクォーテーションの中の[ >](空白等)は判定しないような > 定義に出来るのでしょうか。 できなかありませんが、一目でわかる記述にはならないので あまりお勧めはできません。 #わかりやすい記述にするとパフォーマンスが悪いものになるし
補足
回答有難うございます。 今回WORDから自動生成されたHtmlを使用しているのですが、属性に'"'が付いてない場合があるようです。 > 以下のように定義を "="から始まり、空白か">"迄と定義した所、 このような定義ではなくてもいいのですが、 <td width=84 colspan=2 valign=top> このようなケースもある為、 =の後の、'"'で囲まれた部分というのは駄目みたいです。 きちんと記述していないなくて申し訳ありませんが、 宜しくお願いします。
補足
*と*?は範囲が違うでしょうか。 *は最大まで範囲をとる。 *?は最小の範囲をとる。 同じ?でも使われ方が違ったりするんですね。 色々説明して頂き本当に有難うございます。 正規表現は勉強しているとなかなか面白いです。