- ベストアンサー
Javaの正規表現を使った画像URLの自動リンクができません
Java(version 1.5.0_05)の正規表現を使った画像URLの自動リンクで 行き詰っています。 通常のリンクタグは pattern = Pattern.compile("(http://|https://){1}[\\w\\.\\-/:&?,=#]+",Pattern.CASE_INSENSITIVE); でうまく変換できているのですが、 画像の場合、 pattern = Pattern.compile("(http://|https://){1}[\\w\\.\\-/:&?,=#]+(jpg|jpeg|gif|png|bmp)",Pattern.CASE_INSENSITIVE); としてもマッチせず、 変換ができません。 正規表現が間違えているのは分かっているのですが、 どこをどう変えたらよいのか教えてください。 宜しくお願いいたします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
うわぁ。だいぶ悩んでしまいました…。もう2時だ。寝よ。 とりあえずメソッドの利用法の間違いですね。 この場合、findを使用すべきです。他の部分にも問題がありそうですけど、正規表現の部分はとりあえず画像URLのマッチの部分はOKかなと。 matches:領域全体をこのパターンとマッチします。 find:入力シーケンスからこのパターンとマッチする次の部分シーケンスを検索します。 あとどうでもいい話ですけど、なんとなくプログラムの雰囲気が、Javaっぽくないなー(Cかな?)とか思いました。
その他の回答 (3)
- bobviv
- ベストアンサー率50% (13/26)
IMGタグ用のパターンを http(s?)://[\\w\\.\\-/:&?,=#]+\\.(jpg|jpeg|gif|png|bmp) 、Aタグ用のパターンを ([^\\p{Punct}])(http(s?)://[\\w\\.\\-/:&?,=#]+)([^\\p{Punct}]) としたうえで、2番目のreplaceAllの引数に $1<A HREF=\"$2\">$2</A>$4 をセットしてみてください。 変更した点は、 1. 先頭の^と後尾の$を削除。 2. 拡張子(.)の前に\\を追加。 3. Aタグ用のパターンについては、IMGタグに変換済みのURLを拾わないように、直前および直後に記号文字がある場合は無視すべく[^\\p{Punct}]を追加。(本来、[^\\"]とすべきでしょうが、私のエディタがエスケープされた"を文字列の終了と勘違いして警告を出して困るので、あえて\p{Punct}としました) 4. 2番目の置換パターンを3の変更に合わせて修正。 動くかどうかよりも、その理由を知ることのほうが大事だと思います。
お礼
正規表現にはあまり触れたことがなく、頂いた回答で「なるほど、そういう考え方をするといいのか!」と新しい発見をしました。 ありがとうとう御座いました。
補足
arakororinさん、bobvivさんの回答と色々試した結果、 以下のようなメソッドになりました。 public static String AutoLink(String s){ //正規表現用変数 Pattern pattern; Matcher matcher; //優先順位に注意 //画像パターン pattern = Pattern.compile("http(s?)://[\\w\\.\\-/:&?,=#]+\\.(jpg|jpeg|gif|png|bmp)",Pattern.CASE_INSENSITIVE); matcher = pattern.matcher(s); if(matcher.find()){//画像なのでイメタグを利用する s = matcher.replaceAll("<IMG SRC=\"$0\">"); } //画像以外のリンクパターン(入力文字列sがhttpで始まるもの以外) pattern = Pattern.compile("([^\"]|\\p{Blank}|\\n|\\r)(http(s?)://[\\w\\.\\-/:&?,=#]+)([^\"]|\\p{Blank}|\\n|\\r)",Pattern.CASE_INSENSITIVE); matcher = pattern.matcher(s); if(matcher.find()){//画像でないのでAタグを利用する s = matcher.replaceAll("$1<A HREF=\"$2\" target=_blank>$2</A>$4"); } //入力文字列sがhttpで始まるもののリンクパターン if(s.substring(0,4).equals("http")){ pattern = Pattern.compile("^http(s?)://[\\w\\.\\-/:&?,=#]+",Pattern.CASE_INSENSITIVE); matcher = pattern.matcher(s); if(matcher.find()){//画像でないのでAタグを利用する s = matcher.replaceAll("<A HREF=\"$0\" target=_blank>$0</A>"); } } return s; } findの箇所は冗長かも知れませんが、今後の機能追加などの為においておこうと思います。
- arakororin
- ベストアンサー率39% (80/205)
すみません。ソースを貼れという言葉では不十分でした。入力の文字列の例を教えていただきたいです。 タブン、画像のはずの文字列でマッチする正規表現ということなのだと思うのですが。私の認識では以下のコードで動くはずだと思うのですが、本当にこれではうまくいきませんか? Pattern patternB = Pattern .compile( "^http(s?)://[\\w\\.\\-/:&?,=#]+.((jpg)|(jpeg)|(gif)|(png)|(bmp))$", Pattern.CASE_INSENSITIVE);
補足
こちらこそ入力文字列がなにかお知らせせずに申し訳ありません。 掲示板として、ユーザに文字列を入力してもらいまして、下記のような 動きになるようにしたいと思っています。 パターン(変換無し): 入力「あいうえお」 変換後「あいうえお」 パターン(Aタグ変換): 入力「あいhttp://www.google.comうえお」 変換後「あい<A HREF="http://www.google.com" TARGET=_BLANK>http://www.google.com</A>うえお」 パターン(IMGタグ変換) 入力「あいうhttp://www.google.com/title.jpgえお」 変換後「あいう<IMG SRC="http://www.google.com/title.jpg">えお」 パターン(混合) 入力「あhttp://www.google.comいうhttp://www.google.com/title.jpgえお」 変換後「あ<A HREF="http://www.google.com" TARGET=_BLANK>http://www.google.com</A>いう<IMG SRC="http://www.google.com/title.jpg">えお」 といったようにURLが入力された場合に、画像ならIMGタグ、それ以外の URLならAタグを使った文字列に変換したいのですが、画像でもAタグに 変換されてしまいます。 Pattern patternB = Pattern .compile( "^http(s?)://[\\w\\.\\-/:&?,=#]+.((jpg)|(jpeg)|(gif)|(png)|(bmp))$", Pattern.CASE_INSENSITIVE); としてみましたが、やはりAタグに変換されてしまいました。
- arakororin
- ベストアンサー率39% (80/205)
まずソースを貼ってください。 そうでなければ的確なアドバイスは難しいです。 Pattern patternB = Pattern .compile( "^http(s?)://[\\w\\.\\-/:&?,=#]+.((jpg)|(jpeg)|(gif)|(png)|(bmp))$", Pattern.CASE_INSENSITIVE); とりあえずこんなんでどうでしょう?
補足
ソースは、 //自動リンク public static String AutoLink(String s){ //正規表現用変数 Pattern pattern; Matcher matcher; pattern = Pattern.compile("(http://|https://){1}[\\w\\.\\-/:&?,=#]+(jpg|jpeg|gif|png|bmp)",Pattern.CASE_INSENSITIVE); matcher = pattern.matcher(s); //優先順位に注意 if(matcher.matches()){//画像なのでイメタグを利用する s = matcher.replaceAll("<IMG SRC=\"$0\">"); }else{//画像でないのでAタグを利用する pattern = Pattern.compile("(http://|https://){1}[\\w\\.\\-/:&?,=#]+",Pattern.CASE_INSENSITIVE); matcher = pattern.matcher(s); s = matcher.replaceAll("<A HREF=\"$0\" target=_blank>$0</A>"); } return s; } になります。 よろしくお願いいたします。
お礼
夜遅くまで考えていただいて大変申し訳ないです... ずっとmatchesを使うものとばかり思っていまして、そこがネックだったんですね。 領域シーケンスというのがいまいちイメージつかめませんでした。 私はC言語からプログラムというものを始めて、Javaはまだ経験が浅いです。 これだけの行数のソースでも雰囲気というものがあるんですね。 長いお付き合いありがとう御座いました。