トップページ⇒php
825コメント240KB

正規表現道場@2ch Part2

■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん02/11/24 22:57ID:LrbVcl3Y
Perlに限らずスクリプト系言語で大活躍の正規表現。
このスレは有用そうな正規表現を紹介したり、どう表現したらいいかわからないときに
質問をしたりするためのスレッドです。
質問するときは使用言語や得たい結果をなるべく詳しく書きましょう。

リンクなどは>>2-5のあたりに。
0083nobodyさん02/12/10 16:33ID:???
>>82
2バイト文字を使うウマシカに付ける薬によいのでは?(w
0084nobodyさん02/12/10 16:45ID:???
多国語ドメインがRFCになるとURLの切り出しがウザそう
0085Name_Not_Found02/12/10 17:02ID:???
>>84
それよか、IRIなんてのがひかえてますよ。
00866602/12/10 22:19ID:???
>>67
ありがとうございます。1バイト目の文字は
\x81-\x9F\xE0-\xFC
ですが、その通りにしてもなぜか>が消えてしまうようです???
例えば<BR>の次に[が来ていると、
<br? こうなってしまいます。

もしかして、s/(?:^|[^1byte目の範囲を書いてね])\[/?/g;
この場合、Shift_JISの1バイト目の文字以外が来たら、
その文字と[を?の文字に変換してしまうのではないでしょうか?

見当違いならすみません・・・
0087nobodyさん02/12/10 22:27ID:???
s/(?=[\x81-\x9F\xE0-\xFC])\[/&#91;/g;

これだと、上手くいったような気がします。
>>67さん、ありがとうございました!
00886602/12/10 22:29ID:???
と思ったらエスケープされてませんでした・・・
0089nobodyさん02/12/10 23:02ID:???
if ($hoge ne 'bookmark' && $hoge=~ /(?:(?!cache).)*/) {

$hogeが'bookmark'だとちゃんと弾くけどcacheが入ってる場合に弾いてくれない。
http://www.din.or.jp/~ohzaki/regex.htm#Without
ここのやつの意味を勘違いしてるのかなぁ。
0090nobodyさん02/12/10 23:22ID:???
/^(?:(?!cache).)*$/
0091nobodyさん02/12/10 23:37ID:???
>>90
ありがとうございます出来ました。
0092Name_Not_Found02/12/11 01:43ID:61zg/eqG
>>86
ああああ、ごめんなさい。
たしかに、1byte目が消えちゃいますね。
()で$1に保存するか、look-behind 正規表現を使えばいいのかな。
(?=...)の look-ahead はそういうケースでは駄目なはず。

$1 の方は、

s/(^|[^範囲])\]/$1&#91;/g

でいいはず。

look-behind は

s/(?<![範囲])\]/$1'amp;#91;/g

かな。こっちは Perl のバージョンが古いと使えない。5.6 あたりなら大丈夫。
00936602/12/11 08:02ID:???
>>92
lookbehindを使えば良かったんですね!
何度もありがとうございました。
0094 02/12/11 17:44ID:YVHUV6QH
質問します。言語はperlです。

>>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つ以上ある場合はどうしたらいいのでしょうか。
00959402/12/11 17:49ID:YVHUV6QH
$foo =~ s/(&gt;&gt;)([1-9][0-9]*)/<a href="#$2">$1$2<\/a>/g;
でございます。
0096Name_Not_Found02/12/11 18:06ID:7uJNDqfw

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 <= $value and $value <= $high ? qq(<a href="#$1">>>$1</a>)
: qq(>>$1) /sge;
00979602/12/11 18:08ID:???
ミスッた。
$value ってなんじゃ…
$1 ね。
00989402/12/11 18:11ID:YVHUV6QH
>>96 早速ありがとうございます。やってみます。
00999402/12/11 18:49ID:YVHUV6QH
なぜかうまくいきません。
恐れながら、$1は、>>にマッチするのではないですか?
すみません教えてください。
01009602/12/11 20:29ID:7uJNDqfw
>>94
(?:..) は $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;
01019602/12/11 20:31ID:7uJNDqfw
というか (?:...) を使う意味ないじゃんね…
意味無いんで外しといてください。
01029402/12/12 00:14ID:pDUwoT6Y
ありがとうございました。
0103nobodyさん02/12/24 22:43ID:???
http://pc.2ch.net/test/read.cgi/php/996105815/961
0104名無しさん03/01/03 00:29ID:yu7P73hS
すいません 教えてください。。 
最短マッチが、いろいろ読んだけどわかりません。phpです。

/* hoge */ hogehoge /* hoge */  の /* */
で囲んだ部分だけ灰色にしたいんです。

ereg_replace("(/\*.+\*/)","<font color=\"gray\">\\1</font>");
こうすると 最初と最後の/* */にマッチしてしまいます。

たぶん、最長マッチだからです。
最短マッチにするには?をつけろと書いてあるけど、どこにつけるかわかりません。

(/\*.+\*/){1,}? こうするとなにも出てきません。

なんか基本的なことがわかってないです。
0105nobodyさん03/01/03 00:46ID:nupLg+Ov
.*?
010610403/01/03 01:09ID:yu7P73hS
/\*.*?\*/ ということでしょうか? なんもでてこないです(;_;)
010710403/01/03 01:23ID:yu7P73hS
/\*.+?\*/ でもでてこないです。なんか勘違いしてるのでしょうか
教えてください・・・
0108nobodyさん03/01/03 01:27ID:nupLg+Ov
うぅーそれ以上はわからない・・

もしかしたらereg()で最短一致は使えないのかも。
preg_replaceでなら上手くいくかも。
010910403/01/03 01:40ID:yu7P73hS
ありがとうございます・・
でもpregでもできません・・(;_;)
というか、なにも表示されないというのがアヤシイです。。
0110nobodyさん03/01/03 01:41ID:???
そんなあなたにPerlをお奨めしますです。。。
0111nobodyさん03/01/03 17:38ID:???
$hoge=$1 if($text=~/(ソ+)/);

このように書いてもソが脳内通りに取得出来ないんですが
どうすればいいんでしょうか?
0112nobodyさん03/01/03 21:33ID:nupLg+Ov
$hoge=$1 if($text=~/((?:ソ)+)/);
011311103/01/04 17:33ID:???
>>112
無事成功しました。
ありがとうございました。
0114山崎渉03/01/15 13:36ID:???
(^^)
0115nobodyさん03/01/18 13:42ID:???
掲示板スクリプト作っているんですが、
URLの抽出前に<>"を文字参照に置き換えると、
URLの抽出を行うと、http://www.yahoo.co.jp">Yahoo</a>
とかもa>までURL扱いになってしまい、困っています。

$msg=~s/(http|ftp|mailto)\:([\w.\@~\/\-\?&=;%#]+)/\<a href=\"$1:$2\">$1:$2<\/a>/g;

URL抽出部分はこんな感じです。
0116nobodyさん03/01/18 13:45ID:hA2YqZMs
変な日本語ですみません。頭がボーとしてて・・・
0117nobodyさん03/01/18 15:29ID:???
>>115
じゃあ、抽出後に<>を置き換える。
後、$1と$2、どうせ結合するならまとめて括弧でくくればいいのに。
011811503/01/18 18:54ID:???
>>117

>じゃあ、抽出後に<>を置き換える。
抽出後に<>を置き換えると、
<aまで&lt;aに置き換わってしまうので・・・

>まとめて括弧でくくれば
そうですね。

で、一旦[link]http://www.yahoo.co.jp[/link]に置き換えてから、
<>を置き換えて、[link]...[/link]を置き換えるというもの考えたんですが、
それだと
=~/\[link\](.*)\[\/link\]/\<a href=\"$1\">$1\<\/a\>/g;
等としても、最初の[link]から最後の[/link]までが置き換わってしまって、
2つlinkが続く場合等に予期しない結果になってしまいます。
0119nobodyさん03/01/18 19:01ID:???
>>118
俺ならタグ付けは表示時に行う。データに妙な情報付けたくないんで。
012011503/01/18 19:23ID:hA2YqZMs
>>119
表示時にタグ付けすると解決する?
0121nobodyさん03/01/18 19:30ID:???
>>120
そだろ。
012211503/01/18 19:33ID:???
でもデータは
&lt;a href=&quot;http://www.yahoo.co.jp/&;quot;&gt;Yahoo&lt;/&gt;
とかになるわけで・・・
0123nobodyさん03/01/18 19:38ID:???
>>122
なんでやねん。

データ:
http://www.2ch.netって死ぬほどおもしれー!

表示:
<a href="http://www.2ch.net">http://www.2ch.net<;/a>って死ぬほどおもしれー!
012411503/01/18 19:47ID:???
違う違う。ユーザが、
<a href="http://www.yahoo.co.jp/">Yahoo!</a>
と投稿した場合。
char str[]="http://www.yahoo.co.jp/";
等でも同じ。(この場合はco.jpの後の"もリンク扱いされてしまう)
0125nobodyさん03/01/18 19:51ID:???
>>124
やめさせろ。以上。
0126nobodyさん03/01/18 19:54ID:???
>>124
<.*?(\"([^\"]+?)\".*?)*..?>
0127nobodyさん03/01/20 08:07ID:vz/F/uwh
http://www.2ch.net/ でも http://2ch.net/ でもマッチする
一番エレガントな書き方ってどういうのですか?あと
$url = 'http://www.2ch.net/';
$url =~ s/2ch/1ch/;
と書いた場合になんで$url のなかの"/"をエスケープしなくても
エラーにならないんでしょうか?
0128nobodyさん03/01/20 08:08ID:???
>>127
http\/\/:[www\.]?2ch\.net\/
0129nobodyさん03/01/20 08:09ID:???
ごめん。まだ寝てるわ
http\/\/:(www\.)?2ch\.net\/
0130nobodyさん03/01/20 11:15ID:???
>>127
> エラーにならないんでしょうか?
エラーになったら誰も使わなくなるから(w
0131nobodyさん03/01/20 19:22ID:gSzazTge
>>127
Perlだと、こう書く。
m#^http//:(?:www\.)?2ch\.net/$#

完全一致だよね。知らないけど。
あと、DNSは大文字小文字を区別しないから、この書き方は間違ってる。

今の場合は、単に正規表現を聞いてるんだから、/をエスケープする必要は無いし、
それに、Perlで使うときも、いちいち/をエスケープするのは、エレガントじゃない。
0132nobodyさん03/01/20 20:43ID:vz/F/uwh
>>131
でも、なんで
s/http://www\.2ch\.net/http://www\.1ch\.net/;
がエラーで
$url = 'http://www\.2ch\.net/';
$b = 'http://www\.1ch\.net/';
$url =~ s/$url/$b/;
がokなんでしょうか?
そのへんの理屈がよく分かりません
0133nobodyさん03/01/20 21:52ID:gSzazTge
構文解析時には、変数は展開されていない。
から、インタプリタはs/ / /を認識できる。
0134nobodyさん03/01/20 22:08ID:???
>>132
s///による置換を行う前に、s///の構文チェックをしているからでしょう多分きっと。
s/http://www\.2ch\.net/http://www\.1ch\.net/;
sの次に/があるので/を区切りとした構文としてチェックしてみる。
3つ目の/以降はスイッチ部。
wwwというスイッチは存在しないので、エラー出力
(Bareword found where operator expected, near "s/http://www")

s/$url/$b/;
構文としてはs///という形になるのでOKなので、
次に、正規表現の文字列となる$urlを正規表現のスタック?に展開して積み込み、
同じく$bを展開部用のスタックに積み込んでいるのではなかろうか。

あくまでも想像。
0135nobodyさん03/01/22 11:39ID:Lm4zDQtU
perl1行でgrepと同じ事する方法キボンヌ。

/(^.*key.*$)/$1/
じゃダメポ。

というのも、とあるテキスト書換えソフトでgrep出来たらいいなと。
0136nobodyさん03/01/22 11:42ID:???
>>135
`grep hoge`
0137nobodyさん03/01/22 11:44ID:???
>>135
foreach(@hoge)
{
if(/^.*key.*$/)
{
push(@a,$_);
}
}
で、良いじゃん。正規表現が合ってるかはは知らんけれど
0138nobodyさん03/01/22 12:04ID:Lm4zDQtU
>>136
grepが使えたらこんな事はしないかと。

>>137
if等は使えないんですよ。
つまりエディタの検索、置換えに指定する事でgrepするようなものです。
0139nobodyさん03/01/22 12:22ID:???
>>138
>つまりエディタの検索、置換えに指定する事でgrepするようなものです。
?
使えない理由になるの?
0140nobodyさん03/01/22 14:10ID:Lm4zDQtU
>>139
例えですけど、メモ帳の置換えでif使えますか?
マクロじゃないですので使えないです。
0141nobodyさん03/01/22 14:35ID:???
>>140
何を訳のわからんことを。
例えダイアログで指定出来るパラメータが一つでも、内部処理ではアホほどif文が多用されているが。
0142nobodyさん03/01/22 15:50ID:???
>>141
内部処理にいくらIFが使われてようが関係ないぞ。
って何の話してるんだ?
0143nobodyさん03/01/22 15:51ID:???
>>142
こっちが聞きたいよ。
0144nobodyさん03/01/22 15:59ID:???
エディタの中の人も大変だな
0145nobodyさん03/01/22 16:47ID:Lm4zDQtU
>>141
何か大きく勘違いなされてるようで。
とにかく、1行(s/find/rep/)の構文だけでgrepと同じ事を出来ないかと言う事です。

スクリプトを組めるなら最初からそうしますが
制約上そのような事ができません。
0146nobodyさん03/01/22 16:49ID:???
>>145
何か根本的に勘違いなされているようなので。
0147nobodyさん03/01/22 17:30ID:Lm4zDQtU
>>146
どういう事でしょうか?
0148nobodyさん03/01/22 17:36ID:???
>>147
はじめから落ち着いて、

・一体どんなアプリケーションを作っているのか。
・一体そのアプリケーションのどの処理で悩んでいるのか。
・ifが使えない制限とは?

位は書いてくれい。
0149nobodyさん03/01/22 17:56ID:Lm4zDQtU
>>148
・使ってるソフト。
よくあるファイル一括書換えソフト。

・やりたい事
メモ帳の置換え(CTRL+H)のような感じで
検索する文字と置換えする文字を指定する事で
ファイルの内容を一気に高速で書き換えられる。
検索文字列及び置換え文字列はBREGEXP.DLLを使う事で
Perlと同等の置換えが指定できる。
その検索文字列と置換え文字列の指定方法。

・IFが使えない理由。
メモ帳のように検索文字と置換え文字を指定する事しか出来ない為。
ソフトを作ってる訳ではなく使っているだけ。

です。以上で分かって頂けるでしょうか?
0150nobodyさん03/01/22 17:58ID:???
>>149
はじめからそう書いてくれれば良かったのにね。
無理でしょ。
0151nobodyさん03/01/22 18:06ID:Lm4zDQtU
>>150
何故無理と言い切れるのでしょうか?
0152nobodyさん03/01/22 18:18ID:???
Perlで描いてドロップレットで一発変換。
0153nobodyさん03/01/22 22:05ID:NkPjRdCp
あ、わかった。>>135は、
正規表現は、置換にも使えると聞き、検索っていうとこで、正規表現をオンにして、
自慢のコードをつっこんでみたが、ちゃんと動かないので、調べるのは面倒だから、
2chに書き込んでみた。でどうだ。

で、さらに、正規表現∈Perlだと思っている。と。

キボンヌって言えば仲間になるから大丈夫だと思っていたら大間違いだぞ。
0154nobodyさん03/01/22 22:06ID:???
>>153
マルチにマジレス、カコワルイ。
0155nobodyさん03/01/23 00:35ID:???
>>144
 ああ!ごめん、見逃してた!反応遅くなっちゃってごめん。
 ・・・では改めて。

 中 の 人 な ど い な い !
0156nobodyさん03/01/23 07:11ID:???
>>153-154
ジサクジエンでした。
0157nobodyさん03/01/23 07:48ID:???
>>155->>144
ジサクジエンデシタ
0158nobodyさん03/01/28 00:31ID:2+2ZA9Pr
ググル(crawl4.googlebot.com他)が来たら〜するというプログラムだけど、
if($ENV{'REMOTE_HOST'}=~/crawl[\d]+\.googlebot\.com/){⊥}
でいいのけ?
0159nobodyさん03/01/28 00:52ID:???
>>158
$robots = "crawl4.googlebot.com";
if($robots =~ /crawl[\d]+\.googlebot\.com/ ){ print "kita----!!";}
をローカル環境でテストしてみる。
0160nobodyさん03/01/28 16:58ID:Go6r3Moz
DNSでは、大文字小文字を区別しないので、iを付ける。
それから、後方一致で調べればいい。

↓普通はこう。googlebotドメインだったらいいんでしょ?
$ENV{REMOTE_HOST} =~ /\.googlebot\.com$/i

↓\dを使うなら、こう使う。\d = [0-9]なので
$ENV{REMOTE_HOST} =~ /crawl\d+\.googlebot\.com$/i
0161nobodyさん03/01/29 11:03ID:aizQjUQ4
2chのトリップなんですけど、
$salt =~ s/[^\.-z]/\./go;
の [^\.-z] これって、具体的にはどれを表すんですか?
0162nobodyさん03/01/29 13:00ID:w0j+LU9j
>>161
./0123456789:;<=>?@
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
↑以外
0163nobodyさん03/01/29 20:26ID:VPOVuFRE
>>135
s/^(?:(?!foo).)*$//
でどうよ?

>>150
能無しが煽ってんじゃねーよ。
0164nobodyさん03/01/29 21:05ID:???
>>163
煽りはスピードが命。
0165nobodyさん03/01/29 21:40ID:aizQjUQ4
>>162
ありがとん。
0166nobodyさん03/01/29 21:45ID:Jsuq0iRw
next if ($title !~ s/$word/<B>$&<\/B>/i);
で、$word に「エロ」を入れてやると、「トロ」という言葉にもマッチするんですが、
何故でしょうか?
0167nobodyさん03/01/29 22:08ID:???
>>166
最後の i のせい。
「エ」の2バイト目は "G"
「ト」の2バイト目は "g"
i をつけると大文字小文字を区別しなくなるので、この2つがマッチする。。
0168nobodyさん03/01/29 22:11ID:???
>>166
http://www.din.or.jp/~ohzaki/perl.htm#JP_Match
ここを読んでおけ
0169nobodyさん03/01/29 23:18ID:???
>>164
( ´_ゝ`)フーン
能無し君がまだ初心者相手に威張る為ここに居たんですか。
まぁ分からない事聞かれて逆切れしてるような貴方にはここがお似合いですね。
( ´,_ゝ`)プッ
0170nobodyさん03/02/01 02:36ID:???
>>169
本当は>>163宛に書きたかったの?
0171質問者03/02/02 12:33ID:aPQL5QO2
複数のor条件な文字列を検索したいとして、
一回の検索で、マッチした文字列がどの条件にあたるかを知ることが出来る?

たとえば
対象文字列: abcdefg
検索語彙: (ab)|(fg)
こういうとき、"ab"と"fg"がマッチするということはわかるが
マッチした文字列がそれぞれどの条件だったのかを知りたい。
BREGEXP(Perl5)もしくはVBRegularExpressionで。
一回の検索では無理?
0172nobodyさん03/02/02 12:35ID:???
>>171
プログラム板に帰れ!



とかいって遊んでみる。


$1に入ってないか?
0173質問者03/02/02 12:39ID:aPQL5QO2
>>172
実はプログラム技術板から来た。
正規表現スレがあるのはこの板だけっぽい。

マッチ文字列を取得することは可能なのだが、
何にマッチしたのかを確かめるためにはどうすれば‥‥?
0174nobodyさん03/02/02 12:42ID:???
>>173
つぅか誘導したのはこの俺だ。


マッチさせたい文字列は自明(自分で設定したんだからな)なのだから後はifとeqで比較すればどうだ?
0175質問者03/02/02 17:45ID:aPQL5QO2
>>174
そか、どうも。

マッチした文字列を検索文字列と比較するということ?
>>171で書いた例についていえばそのとおりだが
正規表現でマッチさせたものについて知りたいので
単純にifで比較してもしょーがない。
(検索文字列が"a."などのとき、比較してもしょうがない)
かといって正規表現でテストするってのも二度手間だし。
正規表現でうまく書けば出来るとか、
普通そーゆー機能あるよ、とかいうことはないですかー?
0176nobodyさん03/02/02 17:47ID:???
?

$x =~ /(ab)|(cd)/;

if($1 eq "ab")
{
print("ab");
}
0177nobodyさん03/02/02 17:56ID:???
perlなら、もう一度マッチングさせるかな。
なるべく別々に処理を行うようにするけど。
VBとかの機能はマ板で訊いてください。
0178nobodyさん03/02/02 17:58ID:???
>>177
>マ板で訊いてください。

・・・なぜ!?
0179質問者03/02/02 18:20ID:???
>>176-177
ありがと。
もしかして知らないところで世の中便利になってて
一撃で出来るかなーと思ったのですが。
とりあえずあきらめときます。
018017703/02/02 18:57ID:???
>>178
ム板だった。
素で間違えた(w
0181nobodyさん03/02/02 21:59ID:???
>>180
いや、いいんでないの?w
0182nobodyさん03/02/14 01:16ID:???
もげ
■ このスレッドは過去ログ倉庫に格納されています