正規表現道場@2ch Part2
■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん
02/11/24 22:57ID:LrbVcl3Yこのスレは有用そうな正規表現を紹介したり、どう表現したらいいかわからないときに
質問をしたりするためのスレッドです。
質問するときは使用言語や得たい結果をなるべく詳しく書きましょう。
リンクなどは>>2-5のあたりに。
0002nobodyさん
02/11/24 22:58ID:???http://www.din.or.jp/~ohzaki/perl.htm
正規表現メモ
http://www.kt.rim.or.jp/~kbk/regex/regex.html
Regex::Diagram.pm
http://www.cc.rim.or.jp/~midorin/mad-p/RegexDiagram.html
正規表現
http://www.cc.rim.or.jp/~midorin/mad-p/perl/benkyou/PRC2kRegex/
UNIX正規表現入門 目次
http://www01.u-page.so-net.ne.jp/jc4/hiroyuki/rex_index.html
Regular Expression(Riue ちゃんの正規表現講座) - Index
http://www.sixnine.net/regexp/
ほとんどは↓のリンク集にまとまっています。
正規表現最新リンク集2002
http://www2.famille.ne.jp/~akio1998/l_grep.html
0003nobodyさん
02/11/24 23:00ID:???正規表現道場@2ch
http://pc.2ch.net/test/read.cgi/php/996105815/
0004nobodyさん
02/11/25 00:15ID:oyWFxt5Hコード書く度に思い出すはめんどい。ていうか忘れてる。
0005あぼーん
NGNG0006Name_Not_Found
02/11/29 22:13ID:/ULd/3Z00007nobodyさん
02/12/05 05:07ID:5X+JpwfGどうやるんでしょうか?
例えばテキスト中の「パーマン」は全部「プーヤン」に置換したいんだけど、
「パーマン3号」だけはスルーする、という風にするには。
一度全部「プーヤン」に変換してから「プーヤン3号」から「3号」を取る、
という方法しかないんでしょうか?お願いします。
0009nobodyさん
02/12/05 06:15ID:5X+JpwfGやりたいことは掲示板にurlを書くと自動リンクになるようにしたいんですけど、
後で修正しようとすると先ほど自動で貼ったアンカータグの中のurlも、
そのアンカータグで囲まれたurlにも再度アンカータグを貼ってしまいます。
(?!3号)みたいにして括弧で囲んで?!を付ければ無視されるのかなと思い、
$comment =~ s/(?!<a href=\")(https?|ftp|gopher|telnet|whois|news)\:([\w|\:\!\#\$\%\=\&\-\^\`\\\|\@\~\[\{\]\}\;\+\*\,\.\?\/]+)(?!<\/a>)/<a href=\"$1\:$2\" target=\"_blank\">$1\:$2<\/a>/ig;
としてみたのですが無理でした。
説明不足ですいません。
0010Name_Not_Found
02/12/05 06:32ID:???0011nobodyさん
02/12/05 07:02ID:5X+JpwfGそれを修正します。
0012nobodyさん
02/12/05 07:44ID:???すいません、質問の意味がわかりました。
cgiで表示させるだけなら、その時にだけ自動リンクを使えばいいですよね、
でも一日ずつhtmlファイルで保存してそれを読み込んでくるタイプなので、
元ファイルにすでにアンカーが貼られてるんですよ。
だからそれを修正しなければならない、とこういうわけです。
掲示板というよりニュースサイトのようなものを作ってます。
001312
02/12/05 07:47ID:???× アンカー
○ <a href=""></a>
0014Name_Not_Found
02/12/05 08:16ID:0NYAnUxi一日目:
これすごい http://www.aaa.com/article.pl?id=11
二日目:
<a href="http://www.aaa.com/article.pl?id=11">これすごい</a>
もっとすごいの発見 http://def.ghi.com/?bbs=a
三日目:
<a href="http://www.aaa.com/article.pl?id=11">これすごい</a>
<a href="http://def.ghi.com/?bbs=a">もっとすごいの発見</a>
....
以前の記事を修正しないなら、
追加分の生データだけパースして html に追加してく処理考えたほうがいいと思う。
で、アンカータグの中身、というよりタグの中身を処理対象外にする方法は
http://www.din.or.jp/~ohzaki/regex.htm を参照。
001512
02/12/05 10:00ID:5X+JpwfGありがとうございます、やりたかったのは確かにそんな感じです。
正確には、
一日目
これすごい http://www.aaa.com/article.pl?id=11
二日目:
これすごい <a href="http://www.aaa.com/article.pl?id=11">http://www.aaa.com/article.pl?id=11</a>
もっとすごいの発見 http://def.ghi.com/?bbs=a
といった感じです。
で、その大崎さんという方のサイトを見て修正したのですが、
確かにタグの中のurlはそのままになったんですが、タグに囲まれたurlの方が
修正するたびに二重に<a href></a>で囲まれていきます(;´Д`)。
<a href>と</a>の間にあるもの以外を全て置換しろ、という正規表現が書ければいいのですが
自分の力量ではとても、、、。
難しいです。
001612
02/12/05 10:05ID:???0017nobodyさん
02/12/05 10:20ID:???0018Name_Not_Found
02/12/05 10:45ID:0NYAnUxiそれはもう処理の内容を考え直した方がいいと思われ。
基本的に追加なんだろうし。
html をこんな風にして、
<!-- news here -->
これすごい <a href="...">...</a>
で、追加分を html に変換後、
出力ファイルの <!-- news here --> をサーチして追加分をそこに足す、
みたいなやりかたはどう?
過去記事も頻繁に修正する可能性があるなら元データを残すやり方にするべき。
もっとも、リクエスト毎に html に変換するんではなく、
スタティックな html をあらかじめ作っておくってやり方はそのままでいいと思う。
0019Name_Not_Found
02/12/05 10:48ID:???0020nobodyさん
02/12/05 17:44ID:???それじゃ<br>が入ってる場合は最初の行しか置換されないし、
その最初の行も最後の一文字が無視される罠。
002112
02/12/05 19:13ID:5X+JpwfG今17さんのでやってみたのですが、確かに20さんがおっしゃるような結果が出てしまいました。
あと、メールアドレスが置換されないみたいです。
>15
まさにそのやり方です、<!-- news here -->のようなコメントをサーチする。
ただ、僕は修正がすごく多いです、、、。
元データを残すやり方は、人様のスクリプトを改良してるので
一からやり直しになるし、またバージョンアップ版が出た時の互換性とか考えると
ツライですねぇ。
もちろん、著作権表示と改造表示は出してます。
002212
02/12/05 19:37ID:???0023nobodyさん
02/12/06 00:05ID:0LEQc9+/とりあえず10分ほどやってみたが出来なかった、
ウチの上司なら出来ると思うが昨日から出張‥‥
0024nobodyさん
02/12/06 00:14ID:???一旦アンカータグ消せばいいんジャネーノ?的外れ?
0025nobodyさん
02/12/06 00:40ID:???修正用のテキストエリアに読み込む時に、元ファイルが例えば
<a href="http://www.yahoo.co.jp/">http://www.yahoo.co.jp/</a>
こういうのばっかだったらそれでいいかも知れんが、実際は
<a href="http://www.yahoo.co.jp/">これヤフー</a>
みたいのも混ざってるってことでしょ。
0026nobodyさん
02/12/06 00:42ID:???0027Name_Not_Found
02/12/06 03:26ID:N6C9SdnH追加と修正は別フェイズにするの。
修正時は余計な変換処理無しで html を直接弄って、
追加の時は追加分だけ変換処理して <!-- news here --> につっこむの。
ただ、直接 html 弄れるフォームがあるってのは
心理的に好きじゃないなぁ。
なんだか正規表現と関係なくなってきたなぁ…
0028nobodyさん
02/12/06 05:06ID:???「変数$newsの中から、アンカータグの中のものと、アンカータグに囲まれた部分は
無視してそれ以外を置換する」
ということがサクっと簡単に出来るものだと思ってました。
長く引っ張ってしまって申し訳ないです、正規表現、一から出直して勉強してきます。
0029nobodyさん
02/12/06 12:37ID:???$msg =~s{<a href=".*?"><a href=".*?">(.*?)</a></a>}{<a href="$1">$1</a>}g;
0030Name_Not_Found
02/12/06 14:31ID:???そういう処理しなきゃいけない状況が不毛なんだってば。
0033Name_Not_Found
02/12/07 04:46ID:705rdiGCおばかなプログラムが増えていく状況を助長してはいけません。
「ライトついてますか?」でも読んでくれ。
0035Name_Not_Found
02/12/07 11:04ID:???0036nobodyさん
02/12/08 12:52ID:???<code></code>で囲んだ間は、オリジナルタグを無効になるように処理したいです。
でも、<code>〜</code>〜</code>こういう風に書かれたら
途中で終わってしまて困ってます。
どうしたら良いでしょうか?
003836
02/12/08 13:40ID:???簡単に言うと、
<code>〜</code>hogehoge</code>
これを
<blockquote>〜</code>hogehoge</blockquote>
こうやって置き換えをしたいのですが、
<blockquote>〜</blockquote>hogehoge</code>
になってしまいます。
s/<code>(.*?)<\/code>/i;
$t =$1;
$t =~ /</</i;
$t =~ />/>/i;
s/<code>(.*?)<\/code>/<blockquote>$t</blockquote>/i;
ソースはこんな感じです。どうしたらいいでしょう…
0039nobodyさん
02/12/08 14:16ID:???>こういう風に書かれたら
っていうことはユーザーの入力を処理するってこと?
それならまずタグの閉じ忘れチェックをすればいいんじゃないかな。
004037
02/12/08 15:01ID:???s#<code>(.*)</code>#'<blockquote>'.(($_=$1)=~s/(<|>)/$conv{$1}/g,$_).'</blockquote>'#e;
004137
02/12/08 15:03ID:???@conv{qw(< >)}= ('<', '>');
s#<code>(.*)</code>#'<blockquote>'.(($_=$1)=~s/(<|>)/$conv{$1}/g,$_).'</blockquote>'#e;
0042nobodyさん
02/12/08 15:05ID:???$t =~ s/<code>(.*)<\/code>/<blockquote>$1<\/blockquote>/i;
print $t ;
これでどうよ?
0043nobodyさん
02/12/08 15:09ID:???その辺は適当に読み直してくれといいつつ書いてみる。。
$t = '<code>〜</code>hogehoge</code>';
$t =~ /</</i;
$t =~ />/>/i;
$t =~ s/<code>(.*)<\/code>/<blockquote>$1<\/blockquote>/i;
print $t ;
間違ってたらごめんよ。
0044nobodyさん
02/12/08 15:13ID:???$t =~ /</</g;
$t =~ />/>/g;
$t =~ s/<code>(.*)<\/code>/<blockquote>$1<\/blockquote>/i;
痛いな、漏れ。
0045Name_Not_Found
02/12/08 17:44ID:cySwFV0Oとかの場合、どこからどこまでが blockquote?
どういうシチュエーションなのかよくわからんちん。
textarea に書き込まれた文字を処理するのか
テンプレートファイルでの処理用のタグを導入してるのか…
0047Name_Not_Found
02/12/08 18:00ID:cySwFV0O指摘すると切れるし。
0048nobodyさん
02/12/08 18:26ID:???0049Name_Not_Found
02/12/09 06:04ID:7ZfXL1H90050nobodyさん
02/12/09 11:29ID:N8zphpYN↓を書いてみました。
^[0-9]*\.{1}[0-9]$
でも、これだと必ず小数点を書かないといけません…。
例えば「12」という数値を通したい場合
「12.0」にしないとエラーになってしまうのです。
「12」でも通るようにするためにはどう書けば良いのでしょうか。
0051nobodyさん
02/12/09 11:50ID:???.1 の形式を許可するなら
^-?\d+(?:\.\d+)?|\.\d+$
005250
02/12/09 12:07ID:???^\d+(?:\.\d+)?$
とすると希望の動作しました!ありがとうございます。
005350
02/12/09 12:31ID:N8zphpYN^\d+(?:\.\d+)?$
これを丸々否定したいのですが、
^[^\d+(?:\.\d+)?]$
だとダメでした。
どのようにすれば良いでしょうか…。何度もスイマセン。
何がやりたいかというと、とあるcgiでの入力チェックを行う際に
「有効書式設定」「無効書式設定」というのがあります。
そこにフォームからの入力チェックを正規表現で設定できるのですが、
「有効書式設定」に先ほどの正規表現を入力すると
必ず入力しなくてはならなくなりました。
ですので「無効書式設定」に先ほどの正規表現を
丸々否定したものをすれば、必ず入力しなくても良くなるのでは
と思って質問させていただいてます。
005550
02/12/09 17:05ID:N8zphpYN許可したくないものまで許可できてしまいました…。
ですので、「整数と小数、または、0文字を許可」という条件を
「有効書式設定」の所に設定し直そうと思います。
整数と小数の部分は
^\d+(?:\.\d+)?$
でいけてるのですが「または、0文字を許可」の部分を
↑にどのように付け加えればよいのかわかりません。。
すいませんがよろしくお願いします。
0056Name_Not_Found
02/12/09 17:29ID:Pf18ytiH0文字を許可を入れる場合の定石は、
処理ループの(ループだよね?)最初で /^$/ 等でマッチさせる。
一つの正規表現でやるよか速くなる可能性高いからそっちも考えて。
"または" がきたら、普通に if とかの使用も考えること。
005755
02/12/09 17:40ID:N8zphpYN今回、cgiそのものを書いているのではなく
cgiを設定する画面が存在して、その「有効書式設定」部分に
正規表現を書けば、自動的に入力チェックを行ってくれるというものです。
┌―――――――┐
有効書式設定:| |
└―――――――┘
cgiのこのテキストボックスに書くって感じです。
なので、一つの正規表現で解決させたいです。。
0058Name_Not_Found
02/12/09 17:48ID:???なるほど。でしたら、
^(?:\d+(?:\.\d+)?)?$
で。
.0123 とかを許可するんだったら
^(?:\d+)?(?:\.\d+)?$
で。
006036
02/12/09 18:50ID:???>>37,42,45
ありがとうございました、無事変換できました。
つまり、?が要らなかったんですね。
<code>あああ</code>ほげ<code>ほげ</code>ふがふが</code>
つまり、最初と最後の<code></code>のみを変換して、
間に入っているタグは無効にしたかったんです。
かなり悩んでいたので、助かりました。感謝です!
0061nobodyさん
02/12/09 23:44ID:???0063nobodyさん
02/12/10 06:27ID:QO7zNhpw何に対してマッチしたかがわかりません。
例えば
if($ref=~ /ああ/ || $ref=~ /いい/ || $ref=~ /うう/ || $ref=~ /ええ/){
$ref=さっきマッチした語句 , "おお";
}
みたいな処理をする場合、さっきマッチした語句を調べるにはどうしたらいいのでしょうか?
$_ とか$1を当てはめても上手くいかないんですが。
お願いします。
006463
02/12/10 06:34ID:???0065nobodyさん
02/12/10 07:37ID:???みたいなフォーマットの文を
この例では「2ちゃんねる」に当たる部分だけ抜き出したいので
$text=2ちゃんねる&hc=0&hs=0;
$text =~ /format(.*)\&(.*)/:
$hensu=$1;
みたいに書くと、$hensuの中身が
「2ちゃんねる&hc=0」という風に
一番最後にある「&」で区切られてしまいます。
最初に出くわした「&」で区切りたい、という時にはどうしたらいいんでしょうか?
0066nobodyさん
02/12/10 07:51ID:???[→[
]→]
と言う風に置き換えをしたいのですが、下記のようにすると
$msg =~ s/\Q[\E/?/g;
$msg =~ s/\Q]\E/?/g;
ー の文字コードが81 5Bで、 [ の文字コードが5Bなので
ー が文字化けをしてしまいます。
文字コードはShift_JISです。どういう風にすれば文字化けを回避できるでしょうか?
0067Name_Not_Found
02/12/10 10:17ID:SHy7dsCG.* とか .+ は最も長くマッチしようとします。
.*& ってやると後ろの & まで見ちゃうわけですね。
そういう場合は .*? みたいに、後ろに ? を付けると
なるべく短かくマッチしようとするようになります。
>>66
前の文字が Shift JIS の 1byte目じゃなければ置換、ってすればいいのかな。
s/(?:(?:^|[^1byte目の範囲を書いてね])\[)/?/g;
試してないからわからないけど、これでどうでしょう?
0068Name_Not_Found
02/12/10 10:18ID:???括弧余計すぎた。
そと側の (?: .. ) はいらないわな…
0070Name_Not_Found
02/12/10 11:42ID:SHy7dsCGただ、.*? は遅くなることがあるから、
この場合は [^&]*& の方が望ましいです。
0071nobodyさん
02/12/10 12:21ID:???速いのってどんなやつ?
kentでは
$test =~ s/([^=^\"]|^)(https?\:[\w\.\~\-\/\?\&\=\@\;\#\:\%]+)/$1<a href=\"$2\" target=\"_top\">$2<\/a>/g;
ってやってるみたいだけど これ遅くない?
007472
02/12/10 12:44ID:???それを削ってこんな感じ。
$test =~ s/(https?\:\/\/[a-zA-Z\.\~\-\/\?\&\=\@\;\#\:\%_!*'()]+)/<a href=\"$1\">$1<\/a>/g;
ちなみに、[]内はURI使える文字だけど、kentのは不足している。
動作確認していないので、フォローよろしく。
007572
02/12/10 12:59ID:???$test =~ s/(https?\:\/\/[-a-zA-Z0-9.~\/?&=\@;#:%_!*'()+\$,]+)/<a href=\"$1\">$1<\/a>/g;
0076nobodyさん
02/12/10 14:39ID:???ではダメ?
007776
02/12/10 14:41ID:???007876
02/12/10 14:44ID:???かな?
007976
02/12/10 14:45ID:???だ・・・鬱
0084nobodyさん
02/12/10 16:45ID:???0085Name_Not_Found
02/12/10 17:02ID:???それよか、IRIなんてのがひかえてますよ。
008666
02/12/10 22:19ID:???ありがとうございます。1バイト目の文字は
\x81-\x9F\xE0-\xFC
ですが、その通りにしてもなぜか>が消えてしまうようです???
例えば<BR>の次に[が来ていると、
<br? こうなってしまいます。
もしかして、s/(?:^|[^1byte目の範囲を書いてね])\[/?/g;
この場合、Shift_JISの1バイト目の文字以外が来たら、
その文字と[を?の文字に変換してしまうのではないでしょうか?
見当違いならすみません・・・
0087nobodyさん
02/12/10 22:27ID:???これだと、上手くいったような気がします。
>>67さん、ありがとうございました!
008866
02/12/10 22:29ID:???0089nobodyさん
02/12/10 23:02ID:???$hogeが'bookmark'だとちゃんと弾くけどcacheが入ってる場合に弾いてくれない。
http://www.din.or.jp/~ohzaki/regex.htm#Without
ここのやつの意味を勘違いしてるのかなぁ。
0090nobodyさん
02/12/10 23:22ID:???0092Name_Not_Found
02/12/11 01:43ID:61zg/eqGああああ、ごめんなさい。
たしかに、1byte目が消えちゃいますね。
()で$1に保存するか、look-behind 正規表現を使えばいいのかな。
(?=...)の look-ahead はそういうケースでは駄目なはず。
$1 の方は、
s/(^|[^範囲])\]/$1[/g
でいいはず。
look-behind は
s/(?<![範囲])\]/$1'amp;#91;/g
かな。こっちは Perl のバージョンが古いと使えない。5.6 あたりなら大丈夫。
0094
02/12/11 17:44ID:YVHUV6QH>>94という具合に
ページ内にリンク先がある場合に限ってリンクを張りたいのですが
どうしたらいいでしょうか。
【悪い例】
$foo=">>1 hogehoge\n>>2 hogehoge\n"; #置換対象文字列
$num="94"; #最新レスの番号
$max="100" ; #1ページあたりの表示件数
if(($num>$2)&&($2>$num-$max)){
$foo =~ s/(>>)([1-9][0-9]*)/<a href="#$2">$1$2<\/a>/g;
}
置換以前の$2では当然うまくいきませんです。
しかも、置換対象が2つ以上ある場合はどうしたらいいのでしょうか。
009594
02/12/11 17:49ID:YVHUV6QHでございます。
0096Name_Not_Found
02/12/11 18:06ID:7uJNDqfwmy $max =100; # これは range で
my $num =94; # こっちが max の方がいいような気もするけど。
my $foo=<<EOB;
>>1 hogehoge
>>2 hogehoge
EOB
my ( $high, $low ) =( $num, $num - $max );
$foo =~s/(?:>>)(\d+)/
$low <= $value and $value <= $high ? qq(<a href="#$1">>>$1</a>)
: qq(>>$1) /sge;
009796
02/12/11 18:08ID:???$value ってなんじゃ…
$1 ね。
009894
02/12/11 18:11ID:YVHUV6QH009994
02/12/11 18:49ID:YVHUV6QH恐れながら、$1は、>>にマッチするのではないですか?
すみません教えてください。
010096
02/12/11 20:29ID:7uJNDqfw(?:..) は $1..9 に値を保存しません。
なので $1 で問題ないです。
動かなかった理由は / がクォートされてなかったのと
置換文字列を一行に纒めなてかったからのようでした。
なので、s/// の替りに s{}{} を使っときます。
my $max =100; # これは range で
my $num =94; # こっちが max の方がいいような気もするけど。
my $foo=<<EOB;
>>1 hogehoge
>>2 hogehoge
EOB
my ( $high, $low ) =( $num, $num - $max );
$foo =~s{(?:>>)(\d+)}{
$low <= $1 and $1 <= $high ? qq(<a href="#$1">>>$1</a>)
: qq(>>$1) }sge;
010196
02/12/11 20:31ID:7uJNDqfw意味無いんで外しといてください。
■ このスレッドは過去ログ倉庫に格納されています