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

正規表現道場@2ch Part2

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

リンクなどは>>2-5のあたりに。
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:???
もげ
0183nobodyさん03/02/17 07:11ID:tFA1sH7S
/hoge/piyo/foo\/bar/baka/
という文字列を split して
[ 'hoge', 'piyo', 'foo\/bar', baka ]
という配列を得たいのですが、/ で split するけど \/ では split しない
ってのはどう表せますか?
0184nobodyさん03/02/17 08:04ID:???
[^\\]\/
0185nobodyさん03/02/17 10:03ID:???
>>184
バックスラッシュを一般化して使いたい場合を考えると split するより

my $path ='/hoge/piyo/foo\\/bar/baka/';
my @nodes;

foreach my $elem ( $path =~m%(?:^|\G/)((?:\\.|[^/])+)%g ){
$elem =~s/\\(.)/$1/g; # バックスラッシュを取り除く場合。
push( @nodes, $elem );
}

みたいなのの方がいいと思う。
これだと

/hoge/piyo/foo\/bar\\/baka/ => ['hoge','piyo','foo/bar\','baka']

みたいなのにも対応出来るし。

s///g 使って無理矢理1ステートメントにするのもアリか。
018618303/02/17 11:44ID:???
ありがとうございました
0187nobodyたん03/02/18 01:11ID:???
FYI
@hoge = split m[(?<!\\)/], $path;
0188nobodyさん03/02/18 18:45ID:???
strong 要素内の“</p><p>”を取り除くため、以下のように書いてみたんです。

while ($value =~ /(<strong>.*?)<\/p><p>(.*?<\/strong>)/)
{
$value =~ s/(<strong>.*?)<\/p><p>(.*?<\/strong>)/\1\2/g;
}

※ $value に HTML が入っている。

初めはこれでも問題なかったんですけど、例えば、

$value = "<p><strong>あ</strong></p><p><strong>い</strong></p><p><strong>う</strong>";

のとき、置換後の $value は、

$value = "<p><strong>あ</strong><strong>い</strong><strong>う</strong>";

となってしまいます。この書き方で大丈夫だと思っていたのに、どうなってるんでしょうか・・・
0189nobodyさん03/02/18 18:57ID:???
>>188
<strong>.*?</p><p>.*?</strong> だと、

<strong> => <strong>
あ</strong> => .*?
</p><p> => </p><p>
<strong>い => .*?
</strong> => </strong>

ってマッチしちゃうよ。

$value =~s{<strong>(.*?)</strong>}{
my $tmp =$1;
$tmp =~s|</p><p>||g;
"<strong>$tmp</strong>";
}ge;

とか。もっと良いやり方ありそうだけど。

019018803/02/18 19:13ID:???
ごめんなさいごめんなさい。もの凄く馬鹿なことを書いてしまいました。
あまりの睡魔に襲われて、今 コタツで寝ながら考えていたのですが、私の書き方だと strong 要素内に </p><p> がない場合を考えてないわけですよね。
本当に申し訳ございません・・・

>>189
有り難うございます。
教えて頂いた方法ですが、あとで勉強しながら考えてみます。
どうも私ではすぐには理解できそうにないもので。

とにかく有り難うございました。
0191nobodyさん03/02/18 20:27ID:???
眠い時って、まともなprog書くの無理だよな。
0192nobodyさん03/02/18 23:46ID:oZOSGD0m
正規表現を初めて2日目です(ごめんなさい)文字列の置換だとか検索に感動してます(申し訳ない)。
正規表現を勉強し始めた理由は、以下の質問からです。
192.168.1.8が、192.168.1.0/24 のネットワークアドレスに含まれているかどうかを
判定する正規表現を書くことは可能でしょうか。
よろしくおながいします。
0193nobodyさん03/02/18 23:48ID:???
人間用表記から、ビット列に直して、ビット演算で適当にやったほうが速いような気がするぞう。
0194nobodyさん03/02/18 23:50ID:???
>192.168.1.8が、192.168.1.0/24 のネットワークアドレスに含まれているかどうかを

ならtrueなのは自明だけど。
019519203/02/19 00:13ID:bka3cebn
>>193
ありがとうございます。やっぱし、正規表現よりは普通にプログラムで
やったほうが良いですか、、ちなにみJava使いです。んー、書いたことないので
なやみます。
0196nobodyさん03/02/19 00:49ID:???
>>195
無視された・・・Java.util.regex使いなのに無視された。
0197nobodyさん03/02/19 00:59ID:???
ビットマスクが8の倍数なら正規表現でも簡単だけど・・
0198nobodyさん03/02/19 01:00ID:???
あぁ。サブネットマスクだった。
0199nobodyさん03/02/19 01:21ID:???
正規表現雑技団とかでやりそうなネタだな。
020019203/02/19 02:16ID:bka3cebn
>>196
ええ、あれ、なんか、無視しちゃうような悪いことしちゃいましたか?
すいません、何かサンプル教えて下さるとうれしいす。。。
0201nobodyさん03/02/19 02:23ID:???
これがスッキリとした正規表現で書けるっていうなら見物だな。
0202nobodyさん03/02/19 16:59ID:oL6d+rQl
select * from testtable where name = 'hoge's name';
という文字列があり、
name = 'hoge's name'の、内側の'だけをエスケープして置換えたいのです。

つまり
select * from testtable where name = 'hoge\'s name';
としたいのです。
ただし外側の'は必要ですのでエスケープしたくないのです。

込み入った例を書くと文字列が
name = ''''' and value = '''' の場合は、
name = '\'\'\'' and value = '\'\''

にしたいのですが、このような複雑な処理を正規表現で行うのは無理なのでしょうか?
0203nobodyさん03/02/19 17:09ID:???
>>202
最大マッチで検索。
0204nobodyさん03/02/19 17:45ID:???
>>202
> 込み入った例を書くと文字列が
> name = ''''' and value = '''' の場合は、

最大マッチでも難しそう・・・
0205nobodyさん03/02/19 18:15ID:???
無理だろう、これは。

SQL だと 文字リテラルのでてくる場所たくさんあるから
個数限定ってわけにもいかないし。

対になってるわけでもないし。

'' ' ' '' ' ' ' '

こんな文字列からクオートすべきのを見つけろ、ってのとかわらんもん。

どういう案件かはわかんないけど、
SQL に置き換える段階でクオートしなかったのが敗因ですね…
0206nobodyさん03/02/21 12:55ID:6n4aSTAx
>>203-205
了解です。
楽しようとせずSQL文を完成する前に
ひとつずつ置換えるようにします。

どうもでした。
0207nobodyさん03/02/21 15:31ID:???
>>206
お役にたてず申し分けない。
0208nobodyさん03/02/21 15:37ID:???
せめて一行に一回しか出て来ないとか、''の両端は必ず空白とかの目印があればいけそうだけど。
0209nobodyさん03/02/21 22:45ID:Kv1GvIlP
初歩的なあれですが、()のなかに()があって、
そのなかに | があっても大丈夫ですか?
/(2ch\.net|1ch\.(com|org))/
みたいな・・
0210nobodyさん03/02/21 22:52ID:???
>>209
.に行っているように\でエスケープしてください。
0211nobodyさん03/02/21 23:19ID:???
>>209
えっと・・あとどれをエスケープするんでしょうか?
この場合合致させたいのは
2ch.net
1ch.com
1ch.org
です
0212nobodyさん03/02/21 23:26ID:???
>>211
基礎から勉強し直せ。
0213nobodyさん03/02/22 10:01ID:???
てゆーか、それくらいとっとと自分で試してみればいいのに。
0214nobodyさん03/02/22 10:12ID:???
でもまあ、サーバー上でしか実験出来ないような環境作っちゃった場合は
聞いた方がはやいやーってなっちゃうだろうね。

0215nobodyさん03/02/22 10:46ID:???
>>214
>でもまあ、サーバー上でしか実験出来ないような環境作っちゃった

それ、何もしてないってことじゃん。
0216初心者質問者03/02/22 17:49ID:Db6aP06C
ダブルクオーテーションで括られた文字列の、
ダブルクォーテーション内部だけをマッチさせたいんですけど。
$1使わないと無理?
0217nobodyさん03/02/22 17:53ID:???
>>216
"が偶数回出てきてる行は囲まれてるな。
0218nobodyさん03/02/22 18:52ID:???
>>214
ActivePerlでもなんでも入れれば一発だろうにな。
怠惰な奴は嫌われる。
0219nobodyさん03/02/24 12:33ID:fQYme6i5
質問です。
ある文字列から始まらない任意の文字列、というのは
どうなって書けばいいんでしょうか。
例えば、<a href...>以外のタグを見つけるといった場合ですが、
文字列a hrefから始まらない、という事で
/<[^(a href)][^>]*>/
という感じかと思ったんですが、これではダメなようなので・・・。
0220nobodyさん03/02/24 18:33ID:???
>>219
!~ /^ある文字列から始まらない任意の文字列/
0221nobodyさん03/02/24 18:51ID:???
この場合、否定先読み、否定後読みを使うんじゃないかね?
0222nobodyさん03/02/24 22:21ID:???
Perl5の場合は、正規表現の拡張構文を使うとこんな感じ。

/<(?!a href).+?>/
0223nobodyさん03/03/03 16:51ID:PjU+W5oK
前スレに似たような質問を見つけて読んだけど・・・
なんか「知らんヤツ書くな!!」とかで正しいのかどうか解りません。。
どなたかご教授お願いします。

言語:Perl 掲示板CGIを作っています。
やりたいこと:特定のタグ以外は無効にする。
私が考えた処理は・・・指定したタグの中身に合致しなかったら消す。
@yukotag = "('b'.'/b'.'u'.'/u')";
if ($value ne "<@yukotag>") {
$value =~ s/<(.*)>//g;
}
でもこれではそもそも動かない・・・エラーにはならないけど。
#有効になるべきタグも消えてしまいます・
どうしたらよいのでしょう。
022422303/03/03 16:53ID:PjU+W5oK
もう一個考えた・・

if ($value ne "<(b|\/b)>") {
$value =~ s/<(.*)>//g;
}
0225nobodyさん03/03/03 16:55ID:???
全てのタグをエンティティに変換し、その後許可タグだけ戻すのが王道。
0226nobodyさん03/03/03 17:27ID:???
>>223-224
Perlを基礎から勉強してください。
基本的な考え方は>>225の通り。こんな感じで。

@yukotag = ('a','u');
$value =~ s/<(\/?.*?)>/<$1>/g;
map { $value =~ s/<(\/?$_.*?)>/<$1>/ig } @yukotag;
0227nobodyさん03/03/05 12:28ID:vWidvRyz
改行二回にマッチさせたいんだけど

$_=~/\n{2,}/g

ではだめれすか?
0228nobodyさん03/03/05 12:30ID:???
>>227
ダメだったんですか?
0229nobodyさん03/03/05 12:33ID:???
my $kaigyou = '(?:・r・n|・r|・n)'
$_ =~ /${kaigyou}{2,}/$nanika/g
023022703/03/05 12:37ID:???
マッチしませんれした
0231nobodyさん03/03/05 20:15ID:???
>>230
$_ =~ /\n{2,}/gs;
023223003/03/05 22:23ID:???
$a="aaa\nddd\nfff\n";
if($a=~/\n{2,}/gs){print"OK!\n";}

?????????????????????????????

0233nobodyさん03/03/05 23:11ID:???
>>232
Safariかよ。
0234nobodyさん03/03/05 23:36ID:???
>>232
おいおい、「改行ニ回」ってそういう意味かよ。
上の回答者はみんな、あんたが「ふたつ(以上)連続する改行」に
マッチさせたがってると思ったんだよ、あんたの質問と例を読んで。

$a = "aaa\nddd\nfff\n";
if(($a =~ s/\n/\n/gs) >= 2) { print "OK!\n"; }
023523003/03/06 03:31ID:???
スマソ
激しく反省
0236nobodyさん03/03/06 03:53ID:???
ネストした括弧へのマッチを一つの正規表現で表すことってできるかな。

((a.b)(c.d)(e(f(g.hij)))k) -> マッチ
((bcd))) -> だめ。

■ このスレッドは過去ログ倉庫に格納されています