PHPの正規表現による置換の質問です。

src="hoge"
href="hoge"
のパターンを探し
src="foo"
href="foo"
に置換する書き方(関数も含めた実行ステートメントでお願いします)を教えてください。
シングルクォートでも対応できるようにお願いします。

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:
  • 終了:2010/04/13 13:20:02
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:rouge_2008 No.1

回答回数595ベストアンサー獲得回数351

ポイント60pt

以下で大丈夫だと思いますが、希望通りの動作になったでしょうか?

$text = "<div>\r\n<a href='test-hoge.html' target='_blank'>リンク1</a><br>\r\n<a href=\"hoge.html\">リンク2</a><br>\r\n";
$text .= "<a href='abchoge-test.html' target='_blank'><img src=\"/images/hoge.gif\">テスト画像1</a><br>\r\n</div>\r\n";

$pattern = "/((?:src|href)=(?:\"|'))(.*?)hoge(.*?)(\"|')/";

$text = preg_replace($pattern, "$1$2foo$3$4", $text);

echo $text;

hogeはファイル名だと思いますので、前後に文字があっても大丈夫なようにしてみました。

上記で希望通りの動作にならない場合は、返信で状況を詳しく教えてください。

※コメント欄を開けて置いてくださった方がフォローしやすいです。

http://php.net/manual/ja/function.preg-replace.php

id:P-mako

早速のご回答ありがとうございました&真意を汲み取っていただき、ありがとうございました。

訂正します。問題なく動作しました。ありがとうございました。

2010/04/13 13:05:58

その他の回答1件)

id:rouge_2008 No.1

回答回数595ベストアンサー獲得回数351ここでベストアンサー

ポイント60pt

以下で大丈夫だと思いますが、希望通りの動作になったでしょうか?

$text = "<div>\r\n<a href='test-hoge.html' target='_blank'>リンク1</a><br>\r\n<a href=\"hoge.html\">リンク2</a><br>\r\n";
$text .= "<a href='abchoge-test.html' target='_blank'><img src=\"/images/hoge.gif\">テスト画像1</a><br>\r\n</div>\r\n";

$pattern = "/((?:src|href)=(?:\"|'))(.*?)hoge(.*?)(\"|')/";

$text = preg_replace($pattern, "$1$2foo$3$4", $text);

echo $text;

hogeはファイル名だと思いますので、前後に文字があっても大丈夫なようにしてみました。

上記で希望通りの動作にならない場合は、返信で状況を詳しく教えてください。

※コメント欄を開けて置いてくださった方がフォローしやすいです。

http://php.net/manual/ja/function.preg-replace.php

id:P-mako

早速のご回答ありがとうございました&真意を汲み取っていただき、ありがとうございました。

訂正します。問題なく動作しました。ありがとうございました。

2010/04/13 13:05:58
id:hikawa244 No.2

回答回数1ベストアンサー獲得回数0

ポイント10pt

「PHP」で「正規表現」だと、プロの方ですよね。

こういうところで質問する前に、

・まず、きちんと基礎を学ぶ。

・そういう仕事がきたら、うんざりしながら、あれこれ試す。

が、正解です。

人に頼っていては、スキルは身につきません。

「会社に火をつけてやろうか」くらいの思いをすることで、プログラマはスキルアップできるのです。

(もちろん、実際に火をつけたらダメよ。(^^))


ただ、

>2010-04-09 02:31:18

に、レスをつけているっていうのは、相当、切羽詰まっているのかな?

ということで、こんな感じでは如何?

<html>

<head>

<title>rex test</title>

<meta http-equiv="content-type" content="text/html; charset=utf-8">

</head>

function foo($doc, $a, $b)

{

return preg_replace(array("/src=[\"'][^\"*][\"']{[^Hh]*}href=[\"'][^\"'*][\"']/i")

, array("src=\"" . $a . "\"\\1href=\"" . $b . "\"")

, $doc);

}

?>

<body>

echo foo('', '1', '2');

echo foo("", '1', '2');

?>

</body>

</html>

ちなみに、これだと、src と href の順番が逆の場合、ヒットしません。

また、クォーテーションのシングルとダブルの判定が、必ずしも厳密ではありません。

まぁ、順番が逆の場合は、入れ替えたパターンでもう一度やれば済みます。

シングルとダブルは、ソースがちゃんとしているという前提で…

でも、これでうまくいかない場合、「正規表現」が理解できていないと、手助けにならないかも…


「正規表現」は、普通によく出ます。

正直、少し、とっつきにくいです。

でも、きちんと学べば、あなたにとって、強力な助っ人になるはずです。

困ったことに、覚えても、カットアンドトライになる、面倒臭い奴ですけどね。

これを機会に、勉強してみてください。

あなたの問題が解決しますように…


※回答にURLが必須です

って、出てしまいました。

どうすれば、いいんだろう?

とりあえず、http://ja.wikipedia.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%B...とか?

id:P-mako

アドバイス、真意の汲み取りありがとうございます。

正規表現の基礎的なところは多少は理解しています。

PHP(preg系はPerlですかね)以外にも、秀丸やDreamWeaverの正規表現も多少は使ったこともあり、

実行系によって微妙な差異があること、だけではないんですが、正確に「書けるようになる」ことは

その頻度やレベルからあまり重要ではありません。ぎりぎり「読めれば良い」程度で、基礎的といって

いるのは、そんなに長く複雑でない正規表現でなければ読めるんです。英語と近いですね。

とくに今回ものは、比較的、頻出すると思われる内容なので、この手のものは、知っている人に

聞くのが手っ取り早いです。

もちろんGoogleで検索してみたのですが、見落としているのか、ワードが適当でなかったのか、

あまり相応しいものが見つからなかったので質問したんですけどね。

何も詳しい説明をつけずに、ぽーんと乱暴な質問でした。

2010/04/13 13:19:32
  • id:rouge_2008
    相対パスを絶対パス(WEBルートからのパス?)に変更したいのでしたら、以下のようにしてはいかがでしょうか?
    ちょっとゴチャゴチャしているかもしれませんが・・・

    <?php

    $webroot = "/home/www/user1"; //WEBルートのパスを指定(※最後をスラッシュで閉じないでください。)
    $webroot = preg_quote($webroot, "/");

    $text = "<div>\r\n<a href='./hoge1.html' target='_blank'>リンク1</a><br>\r\n<a href=\"./linktest.html\">リンク2</a><br>\r\n";
    $text .= "<a href=\"../xyz/test-link.html\">リンク3</a><br>\r\n<a href=\"../images/dog1.bmp\">画像リンク1</a><br>\r\n";
    $text .= "<a href=\"./img/cat1.png\"><img src='./img/cat1.png'>テスト画像1</a><br>\r\n</div>\r\n";

    $pattern = "/((?:src|href)={1}(?:\"|'))([^>]*?)(\"|')/";

    preg_match_all($pattern, $text, $matches);

    for($n=0;$n<count($matches[2]);$n++) {
    $path[$n] = realpath($matches[2][$n]);
    $path[$n] = preg_replace("/\\\/", "/", $path[$n]); //Windows用の変換

    // WEBルートからのパスに変換
    $path[$n] = preg_replace("/".$webroot."/", "", $path[$n]);

    $matches[2][$n] = preg_quote($matches[2][$n], "/"); //検索パターンの正規表現の特殊文字をクオートする
    $text = preg_replace("/".$matches[2][$n]."/", $path[$n], $text);
    }

    echo $text;

    ?>


    ※リンク先のファイルが実在しないとsrcやhrefの指定が空になります。
    動作テストも実在するファイルを対象に行ってください。

    一応、WindowsとLinux両方の環境で動くようにしたつもりですが、Windowsでしかテストしていません。

    ※表示する時に書き替えているだけですので、ファイルの記述自体を変更したい場合は、さらに別の処理が必要になります。
  • id:rouge_2008
    オリジナル関数を作成した場合です。
    使い回しができるので、この方がいいかもしれません。

    「my_replace.php」
    <?php

    function myReplace($text) {

    global $text, $webroot;

    $pattern = "@((?:href|src)=(?:'|\"))([^>]+?)('|\")@";

    preg_match_all($pattern, $text, $matches);

    for($n=0;$n<count($matches[2]);$n++) {
    //realpathでファイルの絶対パスを取得
    $path[$n] = realpath($matches[2][$n]);
    $path[$n] = preg_replace("@\\\@", "/", $path[$n]); //Windows用の変換
    $path[$n] = preg_replace("@".$webroot."@", "", $path[$n]);
    $matches[2][$n] = preg_quote($matches[2][$n], "/");
    $text = preg_replace("/".$matches[2][$n]."/", $path[$n], $text);
    }

    return $text;

    }

    ?>

    使用する側のPHPファイル
    <?php

    require_once("my_replace.php");

    $webroot = "/home/www/user1"; //WEBルートのパスを指定(※最後をスラッシュで閉じないでください。)

    $text = file_get_contents("hoge1.html"); //書き替え対象のファイルを開いて変数に格納します。
    myReplace($text); //関数を呼び出して処理します。
    echo $text; //書き替え後のHTMLテキストを確認したい場合

    file_put_contents("./testwrite/hoge1.html", $text); //変換後のテキストをファイルに書き込む場合(※ファイルのパスを指定してください。)

    ?>

    ※Linuxなどで実行する場合は、書き込むフォルダのアクセス権に注意してください。
    ※例のように、書き込むファイルは、開いたファイルとは別にするか、事前にバックアップを取ってから実行する事をお勧めします。

    上記で希望通りの事が出来ているでしょうか?
    希望とは違う場合は、どのようにしたいのか、対象のファイルの中身などももう少し詳しく教えてください。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません