いちばん失敗した人決定戦

perlで書かれた掲示板への書き込みの際、メッセージの中のURLに#がある場合、その中の#を%23にするのに次のようになっています。

my $char = '-_\.!~*\'()a-zA-Z0-9;/?:@&=+$,%#';
$MsgTrans =~ s|(https?:\/\/[$char]+)|&change($1)|sge;

sub change{
my ($line) = @_;
if($line =~ m|(https?:\/\/[$char]+)\#([$char]+)|){
$line = "<a href=\"$RS$1%23$2\">$1#$2</a>";
}else{
$line = "<a href=\"$RS$line\">$line</a>";
}
return $line;
}

これを踏襲しつつ、特定のURLの場合、$RSがつかないようにするにはどう書けばよいですか。

A 回答 (4件)

ん~, まあそのくらいじゃないかなぁ....



あんまりいじりようがない気もする.
    • good
    • 0
この回答へのお礼

最後まで相談にのってくださり有難うございました。
ソースコードも詳細に説明してくださってとても嬉しかったです。
素人の拙い説明でこちらの意図を汲み取っていただけて本当に感謝しています。

お礼日時:2015/11/29 01:43

まず, change の中の


$line = "<a href=\"$RS$1%23$2\">$1#$2</a>";
についてよく見てみると $1#$2 は $line と同じだから実は
$line = "<a href=\"$RS$1%23$2\">$line</a>";
と直すことができる. で, Perl 5.14 以降では s/// に /r フラグがあって
my $newuri = $line =~ s|(https?:\/\/[$char]+)\#([$char]+)|$1%23$2|r;
とすると, さらに
$line = "<a href=\"$RS$line\">$line</a>";
もまとめて
$line = "<a href=\"$RS$newuri\">$line</a>";
とすることができる. ここで $line にあるすべての # を置き換えるには s/#/%23/g でできることから, 現在のコードは
sub change{
my ($line) = @_;
my $newuri = $line =~ s/#/%23/gr;
$line = "<a href=\"$RS$newuri\">$line</a>";
return $line;
}
と書き直すことができる.

あとは「特定のURLの場合、$RSがつかないようにする」だが, これを含めると
sub change{
my ($line) = @_;
my $newuri = $line =~ s/#/%23/gr;
if (特定の URL) {
$line = "<a href=\"$newuri\">$line</a>";
} else {
$line = "<a href=\"$RS$newuri\">$line</a>";
}
return $line;
}
という感じになる. あとは「特定の URL」の判定だが, そこは知らん. 単純には
if ($line =~ m|なんか|)
という判定でいけるかもしれん. あと「特定のURLをいくつか指定できるように」ということだと
その「特定の URL の指定」はどうするの?
ってとこから話がはじまる. 配列にいれるなら配列にいれるで「どのようになっているのか」がほしいねぇ.

ついでだが, 例えば
$MsgTrans =~ s|(https?:\/\/[$char]+)|&change($1)|sge;
はなんで / をエスケープしてるの?
    • good
    • 0
この回答へのお礼

大変ありがとうございました。
当初思っていた通りの動作に出来ました。
if ($line =~ m|なんか|)
の「なんか」の部分に直接http://hogehoge/と記述したのですが動いてくれました。
「特定のURLをいくつか指定できるように」は思ったよりも大変そうなので今回は見送る事にします。
その代わりと言っては何ですが、「特定の URL」の場合は#を%23に変換しないようにしたいことに気づいてしまいました。
%23は別CGIに渡すための変換だったのですが、「特定の URL」の場合は直接リンク先に飛ぶため#の恩恵にあずかれなくなってしまうのです。
そこで、せっかく綺麗にまとめてくださったのに汚してしまって申し訳ないのですが、

sub change{
my ($line) = @_;
if ($line =~ m|http://hogehoge/|) {
my $newuri = $line;
$line = "<a href=\"$newuri\">$line</a>";
} else {
my $newuri = $line =~ s/#/%23/gr;
$line = "<a href=\"$RS$newuri\">$line</a>";
}
return $line;
}

以上のようにしてみました(一応希望通りには動きます)。
これで良いのかどうかも解っていません。
もっとやりようがあれば教えていただけると幸いです。
よろしくお願いいたします。

$MsgTrans =~ s|(https?:\/\/[$char]+)|&change($1)|sge;
のエスケープは何かのコピペだったかも知れません。
無くても正常に動いたので消しておきました。

お礼日時:2015/11/28 04:48

あとちょっと確認することがあった.



・Perl のバージョンはいくつ?
・「特定のURLの場合」はどう判定するつもり?
    • good
    • 0
この回答へのお礼

サーバーのperlのバージョンは5.14.xみたいです。
特定のURLをどう判定するかという意味が判らないのですが、変数$RSは外部サイトへのリンクにアクセスする際の注意事項画面を表示する別CGIへのURLです。
yahooの外部リンクみたいな感じです。2ちゃんのime.nuみたいなものでしょうか。
掲示板を設置した自サイト内へのリンクには不要なので、同サーバー内のURLには適応しないようにしたいのです。
もし可能でしたら特定のURLをいくつか指定できるように出来れば嬉しいです。
こんな説明でご理解いただけるでしょうか?
よろしくお願いいたします。

お礼日時:2015/11/27 05:08

もっとまともな書き方ができないものかなと思いつつちょっと確認.



2回以上 # があったときに最初の 1個しか置き換えないけど, それでいいんだね?
    • good
    • 0
この回答へのお礼

お返事有難うございます。
すみません。よく判っていないもので、このような書き方になってしまいました。
2回以上 # があったときも置き換えられたほうが良いです。
よろしくお願いいたします。

お礼日時:2015/11/26 18:20

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!