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

正規表現道場@2ch Part2

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

リンクなどは>>2-5のあたりに。
0449nobodyさん03/05/11 14:25ID:QXPmJshp
>>448
いいよ
0450nobodyさん03/05/11 15:26ID:???
open FILE, $file or die $!;
read(FILE, $doc, -s FILE);
while( $doc =~ m|<a.*?/a>|isg ){
my $temp = $MATCH;
$temp =~ s/\n//g;
print $temp,"\n";
}

close FILE;
045143503/05/11 16:12ID:???
>>450
<applet><a href="hoge">abc</a>
<address><a href="hoge">abc</a>
<area><a href="hoge">abc</a>

あらゆる可能性も考慮しないと・・・30点
0452nobodyさん 03/05/11 16:24ID:???
{
  my @tag = $_ =~ m/<a([^>]).>/g;
  @uri = map{ m/($http_regx)/; $1; } @tag;
}

$http_regxは自分で調べること
0453nobodyさん 03/05/11 17:16ID:???
>>452訂正
{
  my @tag = $data =~ m/<a([^>].)>/g;
  @uri = map{ m/($http_regx)/; $1; } @tag;
}
0454nobodyさん03/05/11 17:23ID:???
<a [^>]*href=("[^"]+:[^"]+"|'[^']+:[^']+')[^>]*?>
045543503/05/11 17:28ID:???
>>454
 >>451も読んでね。

>>452,>>453は問題外
0456nobodyさん03/05/11 17:45ID:???
>>450
m|<a\s.*?/a>|isg
045743503/05/11 17:56ID:???
>>456
<a name="hoge"><a href="hoge">abc</a>

もうひといき
045845603/05/11 18:01ID:???
>>457
ハァ?<a> はネストしちゃいけないわけですが何か?
0459nobodyさん03/05/11 18:05ID:???
>>458
432> ニュースサイトからアンカータグの部分だけを取得してくる
だから、念には念を入れておくってことで。
046043503/05/11 18:07ID:???
一応IE6のパーサーで95点だから、その辺よろしく。
046145603/05/11 18:10ID:???
>>459
その「念」てなんだよ。点数出すからには採点基準を示せよな。
parse 対象となる HTML の DTD も示せ。BNF でも構わん。
それができないのならこんなの不毛なだけだ。
0462nobodyさん 03/05/11 18:14ID:???
じゃ、コレで如何だよ

my @list = $data =~ /<a(?:[^>]+)?>/g;
@uri = map{ $_=~ /href="?($http_regex)"?/; $1; } grep{/href="?($http_regex)"?/} @list;
046345903/05/11 18:17ID:???
>>461
ごめん、俺は435じゃない。
ネストしないんだからアレでイイと思うんだけど、
ニュースサイトがvalidなHTMLを書いていることは少ないから
「年」って行っただけぽ。
046443503/05/11 18:21ID:???
じゃあ、そろそろ80点以上の例でも示しておこう。

s/<!--.*-->//gs; # 前処理
@gets= $_=~ m!<A\s[^>]*?\bhref=.+?</A>!gsi;

どうだ、、、これで確実に「ゲッツ!」しろYO!
0465nobodyさん 03/05/11 18:25ID:???
>>464
URI以降も含むんでねーのかそれ・・・
046643503/05/11 18:29ID:???
>>465
  >>432嫁

s/<COMMENT>.*</COMMENT>//gs;
s/<!--.*-->//gs;
@gets= m!<A\s[^>]*?\bhref\s*=.+?</A>!gsi;

こんなのがもっと堅実かもな
046743503/05/11 18:30ID:???
間違った。。。iオプションがなくてはな

s/<COMMENT>.*</COMMENT>//gsi;
046843503/05/11 18:36ID:???
まだ間違ってるな

s!<COMMENT>.*</COMMENT>!!gsi;

まったくつくづくだな
046945603/05/11 18:44ID:???
適当にうやむやにごまかそうとしてんじゃねえよ。とっとと「採点基準」を示せよ。
0470あぼーんNGNG
あぼーん
047143503/05/11 18:51ID:???
>>469
だから、<a name="hoge"></a>
   とか
<!--<a href="hoge">--><a href="hoge">abc</a>

とかも考慮すると>>456は68点だな。

採点基準は漏れの直感だ
0472nobodyさん 03/05/11 18:54ID:???
ほれ・・・

s/<!--(?:(?!-->).)*-->//ig;
s/<COMMENT>(?:(?!<\/COMMENT>).)*<\/COMMENT>//gsi;
@gets = m/<a[^>]+href=[^>]*>(?:(?!<\/a>).)*<\/a>/gsi;
047343503/05/11 18:57ID:???
>>472
   できれば>>451を読んで欲しかった

正規表現は冗長になり過ぎると処理が遅くなりにけり
0474nobodyさん 03/05/11 18:58ID:???
なんや・・・
結局イチャモンつけたいだけか・・・
047543503/05/11 19:01ID:???
っていうか、普通に

<area href="url">ってタグあるの知ってる?
047645603/05/11 19:03ID:???
> 採点基準は漏れの直感だ

お前、どっか逝け。
0477nobodyさん 03/05/11 19:03ID:???
@gets = m/<a\s[^>]*href=[^>]*>(?:(?!<\/a>).)*<\/a>/gsi;

じゃ、これでいいんでは?
047843503/05/11 19:05ID:???
>>477
だいぶいい感じだな。できれば最短マッチのほうがシンプルで処理も速いが
047943503/05/11 19:08ID:???
>>476
それじゃ進歩しないぞ。ここは道場だからな。ビシビシいくぞ!
馴れ合いスレじゃないからな。

もちろん漏れが書いたのもまだ不完全なのかも知れん。つっこみどころが
あればつっこんでもっといいものを出せばいいんだ。
0480あぼーんNGNG
あぼーん
048145603/05/11 19:14ID:???
>>479
じゃあ意味の無い点数なんて付けるな。
第一、処理対象となる HTML がどんな仕様なのか前提があいまいで、
あとからコレはダメだアレはダメだなんてのは、
単にいちゃもん付けたいだけとしか思えん。
だったら最初から parse 対象 HTML を全て提示しとけ。
048243503/05/11 19:21ID:???
>>481
いちいち見ず知らずの漏れが付けた点数に反応してどうするよ。
おかしいと思えば無視しろよ。

HTMLの仕様は決まってるだろ。今まで書いたことがいちゃもんだといわれ
ても、漏れがやってるプログラミングの世界ではあらゆる状況を考慮しないと
とんでもないバグになってしまうから、まア職業病だと思ってくれ。
048345603/05/11 19:28ID:???
>>482
> HTMLの仕様は決まってるだろ。

だから漏れが <a> はネストしないって言ったら、 >>457 と言う。
だったらお前の脳内HTML仕様を提示しろと言ってるんだYO!
とんだ職業病だな。
048443503/05/11 19:33ID:???
>>483
確かに、HTML仕様としては>>457はダメだな。>>471を最初から書くべき
だな。ということで68点だな。
0485nobodyさん 03/05/11 19:45ID:???
>>472
だから、わざと冗長な正規表現をかいただけのはなしだが・・・
     ^^^^^^
手前ルールでやられりゃ、腹も立つやろうなぁ・・・
0486あぼーんNGNG
あぼーん
0487nobodyさん03/05/11 20:20ID:???
すげー!変な奴キター!
0488名無しさん@Meadow03/05/12 07:34ID:???
>>487
486みたいな香具師は2chでは普通ですが、何か。
0489nobodyさん03/05/12 07:49ID:???
>>488
>>435のことだよ
0490nobodyさん03/05/12 09:37ID:???
「詳説 正規表現」の第二版が今月下旬に出るみたいだね。
0491nobodyさん03/05/12 10:10ID:???
>>490 diffキボンヌ
0492nobodyさん03/05/12 10:28ID:85k2ng51
前処理でコメントタグ取るなら、
ここまでやるってのはどう?

/<(?:!(?:--[\s\S]*?--\s*)*(>)\s*|(?:script|style|SCRIPT|STYLE)[\s\S]*?<\/(?:script|style|SCRIPT|STYLE)>)/isg;
0493nobodyさん 03/05/12 10:47ID:???
>>492
iつけるんなら、
/<(?:!(?:--[\s\S]*?--\s*)*(>)\s*|(?:script|style)[\s\S]*?<\/(?:script|style)>)/isg;
これでいいんでない?

[\s\S] って .でいいんちゃうかな?
0494nobodyさん03/05/12 10:53ID:85k2ng51
>>493
そうだね、指摘サンクスコ(・∀・)
漏れのソース、i付いてなかった(;´Д`)
0495nobodyさん03/05/12 10:54ID:85k2ng51
とりあえず、コメント削除は、>>493の指摘で完成する物で、かなり逝けると思われ。
ありとあらゆるサイトのコメント入りHTML食わせてみたけど、
まず間違いなく削除してくれる。
100%ではないかもしれないけど。
0496あぼーんNGNG
あぼーん
0497nobodyさん03/05/12 22:56ID:???
サイトによってコメントの定義が違うからな(皮肉
0498nobodyさん03/05/19 22:15ID:pDSpAcPJ
ファイル名だけを変数に取り込む時にフルパスからファイル名だけを取り出す
正規表現はどう書けばいいのでしょうか。
たとえば下のフルパスからhttpd.confだけを取り出すような場合です。
C:\Program Files\Apache Group\Apache\conf\httpd.conf
0499あぼーんNGNG
あぼーん
0500nobodyさん03/05/19 22:36ID:???
>>498
\\([^\\+])$
(\ \以外 末尾)
0501あぼーんNGNG
あぼーん
0502nobodyさん03/05/19 22:58ID:???
>>500
perlなのですがエラーになりました。

-----test.pl------
my $path = $0;
$path =~ \\([^\\+])$;
print "\$path :\n";
print "$path\n";
----------------
0503nobodyさん03/05/19 23:17ID:???
>>502
あたりまえだろう

$path =~ /\\([^\\+])$/;
0504nobodyさん03/05/19 23:23ID:???
>>498

$a='C:\Program Files\Apache Group\Apache\conf\httpd.conf';
($_)=$a=~ /^.+\\(.+)$/;
print;
0505nobodyさん03/05/19 23:26ID:???
>>503
すいません。
改めて試しましたがファイル名test.pが取得できません。

-----test.pl------
my $path = $0;
print "$path\n";
$path =~ /\\([^\\+])$/;
print "\$path :\n";
print "$path\n";
----------------
050650003/05/19 23:33ID:???
すんません。typoです。
× \\([^\\+])$
○ \\([^\\]+)$

>>505
typoに関係なくそのスクリプトは間違っている。
もう一回本読め。
0507nobodyさん03/05/19 23:42ID:???
>>504
さっそく試してみました。
しかしフルパスが入ります。
環境は98です。

-----test.pl------
my $path = $0;
print "$path\n";
$path =~ /^.+\\(.+)$/;
print "\$path :\n";
print "$path\n";
----------------

>>506
ダメでした。
スクリプト自体が間違っていますか?
-----test.pl------
my $path = $0;
print "$path\n";
$path =~ /\\([^\\]+)$/;
print "\$path :\n";
print "$path\n";
----------------
050850403/05/19 23:45ID:???
>>507
資源の無駄だからもう書き込むな
スレが汚れる
0509nobodyさん03/05/19 23:48ID:???
>>508
すいません。
>>504の正規表現でhttpd.confが拾えました。
あとはスクリプトの間違いを修正してみます。
0510nobodyさん03/05/19 23:52ID:???
頭の固い香具師だな
0511nobodyさん03/05/20 00:17ID:???
>>509
>>>504の正規表現でhttpd.confが拾えました。
>>506の正規表現でも拾えてる。
0512nobodyさん03/05/20 00:33ID:???
>>511
500へのお礼を忘れてました。
確かに拾えます。
ですがまだ不具合があるので両方の正規表現を使って試している最中です。

-----test.pl------
my $path = $0;
print "$path\n";
($_)= $path =~ /\\([^\\]+)$/;
print "\$path1 :\n";
print "$_\n";

$a='C:\Program Files\Apache Group\Apache\conf\httpd.conf';
($_)=$a=~ /^.+\\(.+)$/;
print;
----------------
0513nobodyさん03/05/20 00:38ID:???
編集途中のソースが残っていたのでもう無視して下さい。
0514nobodyさん03/05/20 01:10ID:???
フルパスで入力した場合は下のような値が入るので問題ないのですが
$a='C:\Program Files\Apache Group\Apache\conf\httpd.conf';
perl test.plというようにカレントディレクトリから実行して下のような値が入った場合はファイル名を取得できません。
$b='httpd.conf';

$a='C:\Program Files\Apache Group\Apache\conf\httpd.conf';
$b='httpd.conf';
両方の値からhttpd.confだけを抜け出せないでしょうか。
スレ汚しで申し訳ないです。
0515nobodyさん03/05/20 01:11ID:???
#---------------test.pl----------------
my $path1 = $0;
print "$path1\n";
($_)= $path1 =~ /\\([^\\]+)$/;
$path1 = $_;
print "\$path1 :\n";
print "$path1\n\n";

my $path2 = $0;
print "$path2\n";
($_)= $path2 =~ /^.+\\(.+)$/;
$path2 = $_;
print "\$path2 :\n";
print "$path2\n\n";

$a='C:\Program Files\Apache Group\Apache\conf\httpd.conf';
($_)=$a=~ /^.+\\(.+)$/;
print "\$a :\n";
print;
print "\n";
$b='httpd.conf';
($_)=$b=~ /^.+\\(.+)$/;
print "\$b :\n";
print;
#--------------------------------------
0516nobodyさん03/05/20 09:12ID:???
$path =~ /([^\\]\+)$/
print "$1";

っていうか use File::Basename; 使え。
051751503/05/20 12:28ID:???
>>516
ありがとうございます。
皆さんのおかげで完成しました。
use File::Basename; も調べてみます。
051851503/05/20 12:30ID:???
#---------------test.pl----------------
my $path1 = $0;
print "$path1\n";
($_)= $path1 =~ /\\([^\\]+)$/;
$path1 = $&;
print "\$path1 :\n";
print "$path1\n\n";

my $path2 = $0;
print "$path2\n";
($_)= $path2 =~ /^.+\\(.+)$/;
$path2 = $&;
print "\$path2 :\n";
print "$path2\n\n";

my $path3 = $0;
print "$path3\n";
($_)= $path3 =~ /[^\/\\]+$/;
$path3 = $&;
print "\$path3 :\n";
print "$path3\n\n";

my $path4 = $0;
print "$path4\n";
($_)= $path4 =~ /([^\\]\+)$/;
$path4 = $&;
print "\$path4 :\n";
print "$path4\n\n";
#--------------------------------------
051951503/05/20 12:33ID:???
#---------------test.pl----------------
$a='C:\Program Files\Apache Group\Apache\conf\httpd.conf';
($_)=$a=~ /[^\/\\]+$/;
print "\$a :\n";
print "$&\n";
print "\n";
$b='httpd.conf';
($_)=$b=~ /[^\/\\]+$/;
print "\$b :\n";
print "$&\n\n";

$a='C:\Program Files\Apache Group\Apache\conf\httpd.conf';
($_)=$a=~ /([^\\]\+)$/;
print "\$a :\n";
print "$&\n";
print "\n";
$b='httpd.conf';
($_)=$b=~ /([^\\]\+)$/;
print "\$b :\n";
print "$&\n";
#--------------------------------------
スレ汚しに付き合って頂いて感謝でした。
0520nobodyさん03/05/20 12:47ID:ridin1oO
>>515

use File::Basename;
$path = 'C:\Program Files\Apache Group\Apache\conf\httpd.conf';
$file = basename($path);
print $file;
0521あぼーんNGNG
あぼーん
0522山崎渉03/05/22 01:59ID:???
━―━―━―━―━―━―━―━―━[JR山崎駅(^^)]━―━―━―━―━―━―━―━―━―
0523nobodyさん03/05/25 03:32ID:???
山崎のせいで落ちるところだったわ
0524あぼーんNGNG
あぼーん
0525山崎渉03/05/28 17:06ID:???
     ∧_∧
ピュ.ー (  ^^ ) <これからも僕を応援して下さいね(^^)。
  =〔~∪ ̄ ̄〕
  = ◎――◎                      山崎渉
0526nobodyさん03/06/06 19:09ID:GD1DFdBg
文字クラスで、半角英数字とクエスチョンそのものは、
[a-zA-Z0-9,\?]
で良いのでしょうか。

やりたいことは、↓です。
function check($address){
 if ( ereg("^[a-z,A-Z,0-9,\(,\),\.,\_,\/,\+,\?,\-]+@[^.@!\"#$%&'()~^|]+\.[^@!\"#$%&'()~^|]*[^.@!\"#$%&'()~^|]$", $address)){
  return true;
 }
 else{
  return false;
 }
}

$email_1 = "a(a)a?_s-/[email protected]";
$email_2 = "a(a)a_s-/[email protected]";

$email_1も$email_2もtrueが返ってきてほしいのに、
$email_2のみがtrueで返ってきます。。
?そのもにをマッチさせるにはどうすれば良いのでしょうか。

0527あぼーんNGNG
あぼーん
0528nobodyさん03/06/07 00:42ID:???
>>526
PHP だよね?漏れのところ (PHP 4.3.1) ではどっちも true が返るよ?
0529nobodyさん03/06/07 18:56ID:???
>>526
横槍スマソ。
これじゃ駄目かい? ttp://www.din.or.jp/~ohzaki/perl.htm#Mail
053052603/06/09 10:45ID:???
>>528
はい。PHPです。どちらもtrueが返るようになりました。
原因は、「if ( ereg("^[a-z,〜〜〜」を通す前にさらにチェックしていてそこで引っかかっていました。
正規表現とは関係なくてすいませんでした。

>>529
そこはperlだったのですが参考になりそうなページでした。ありがとうございました。
0531yoko03/06/10 13:46ID:QvCU0It/
秀丸でやろうとしているんですが、無理でしょうか?

以下のような形式のテキスト ファイルを扱っています。生徒から備考までを
1 ブロックとして、生徒番号 800 までのブロックがあります。本当は XML か
CSV で管理するべきだと思うので近いうちに変換する予定です。

生徒: 1名前: 田中得意科目: 数学苦手科目: 古文備考: 2 学期より編入

生徒: 2名前: 山田得意科目: 国語苦手科目: 世界史備考: 模試未受験

生徒: 3
..

今正規表現をつかって各データの手直しをしているのですが、とても簡単なと
ころでつまづいています。
"生徒: 2" から "生徒: 2." という具合に、生徒行の数字の後ろにピリオドを
つけたいのですが、どのような表記で置換処理をしていいのかわかりません。
"生徒: [[0-9]+|[02-9]]" で "生徒:" とその数字部分を検索でヒットするこ
とはできるのですが、これを "生徒: [[0-9]+|[02-9]]." で置換しても "生徒:
[[0-9]+|[02-9]]." に入れ替わるだけです。大きな勘違いをしているとは思
うのですが…正規表現の資料をみてもここから先に進むことができません。
すごくつまらない質問だとは思いますが、どなたかみていただけないでしょう
か。

0532yoko03/06/10 13:48ID:???
↑のテキストの部分おかしいですね。
書き直します。

生徒: 1
名前: 田中
得意科目: 数学
苦手科目: 古文
備考: 2 学期より編入

生徒: 2
名前: 山田
得意科目: 国語
苦手科目: 世界史
備考: 模試未受験

生徒: 3
..
0533nobodyさん03/06/10 13:56ID:wps94Nox
CSVファイルに

AAAAA http://www.a.com/
BBBBB http://www.b.com/
CCCCC http://www.c.com/

というタイトルとURLのペアのファイルがあるとします。
で、例えば

「AAAAAはBBBBBでCCCCC」
というテキストを
「<a href="http://www.a.com/">A</a>は<a href="http://www.b.com">〜」
みたいに変換したいです。

上記のペアでしたら、順に検索して置換すれば済むことですが、もし
最後の方に下記みたいなペアがあると
href http://www.href.com/

「<a <a href="http://www.href.com">="http://www.a.com〜」
のように変換されてしまいます。

こういう場合はどうすればいいんでしょうか?
できればそれぞれの置換したい単語が元のテキストを参照できるようにしたいです。

0534nobodyさん03/06/10 14:34ID:???
>>531-532
おそらく秀丸のヘルプ嫁。かと。
正規表現の互換があるかどうか判らないが Perl だと、
s/(生徒: \d?\d)/$1\./g; 等。

>>533
チョソなのでニポンコよくわからないてす。
ニポンコむつかしにだ。
0535nobodyさん03/06/10 23:58ID:???
>531-532
ヘルプ開いて「タグ付き正規表現」というのを読めば幸せになれるかと
0536nobodyさん03/06/11 01:31ID:???
>>533
#!/usr/local/bin/perl

my $text = "AAAAAはBBBBBでCCCCCなhrefさ";

my %dictionary = (
"AAAAA" => "http://www.a.com/",
"BBBBB" => "http://www.b.com/",
"CCCCC" => "http://www.c.com/",
"href" => "http://hre.f.com/",
);

my $pattern = join('|', map { quotemeta($_) } keys(%dictionary));
$text =~ s/(${pattern})/<a href="$dictionary{$1}">$1<\/a>/g;

print "[$text]\n";
0537nobodyさん03/06/11 02:54ID:???
あ、キーは長い順に sort しなきゃダメかな。まいっか。
0538yoko03/06/11 13:19ID:FQ/QXZet
>>535
ありがとうできました!

チュパ (←フェラ)
0539yoko03/06/11 13:20ID:???
>>534
チュパ♪
0540nobodyさん03/06/11 13:54ID:???
>>537
チュパ(←カブラ)
0541nobodyさん03/06/11 14:04ID:???
>>537
チュッパ(←チャップス)
0542nobodyさん03/06/11 16:25ID:u2aqyjyI
解決せぬまま、日が変わってしまいました。
すみません、一つ質問させてください。

HTMLファイル内のアンカータグで指定されているURLを全てエンコードして返すコードを書きましたが、どうも思う
ように動いてくれません。問題のコードは下記となっております。
-----------------------------------------------------
while(<FH>){
  if($_ =~ /\<a.*?href.*?\=.*?\>/ig){
    my $tmp = $_;
    while($tmp =~ /(.*\<a.*?href.*?\=)(.*?)(\>.*?)(\<|\n)/ig){
      my $tmp1 = $1; my $tmp3 = $3;
      my $tmp2 = main::url_encode($2);#エンコードルーチン
      $tmp2 =~ s/\%20//g; $tmp2 =~ s/\%22/\"/g;
      $index_file .= $tmp1 . $tmp2 . $tmp3;
    }
  }
  else{
    $index_file .= $_;
  }
}
-----------------------------------------------------
1行に2つ以上のアンカータグがあった場合を考えてwhileを使用しておりますが、その部分の正規表現に問題が
あるというところまでわかっていながら、全く前進せぬまま日が変わってしまいました。情けないです。
ここの正規表現の区切りとなるものが曖昧なことから、うまく認識してくれず、整形後のHTMLファイルがおかしく
なってしまっているのだと思われます。

もし宜しければ、教えてください。
すみませんが宜しくお願いいたします。
0543nobodyさん03/06/11 16:35ID:???
>>542
誤爆か●朕か悩むところ。
0544nobodyさん03/06/11 19:24ID:???
>>542 ヒント

$reg "s?https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#]";

while ( $txt =~ /$reg/g ) {
 .
 .
 .
}
0545nobodyさん03/06/11 20:35ID:???
>>544
貴重なヒント感謝です。
しかし、厨房な私にはどうも理解できていないみたいです。
せっかくのヒントをいただきながら、本当に申し訳ありません。
0546nobodyさん03/06/12 04:14ID:???
>>545 ヒントその2
ttp://www.din.or.jp/~ohzaki/perl.htm#httpURL
0547nobodyさん03/06/13 23:26ID:sIi8OqiB
(\$|\%|\@)[^a-zA-Z]*?
↑このような正規表現の場合、これは
頭が"$"or"%"or"@"のいずれかから始まって
続いて、アルファベット以外が来る場合。だと思うのですが?
最後の*?はどういう意味でしょうか?
*は0字以上、?は0か1だと覚えているのですが・・・
054854703/06/13 23:27ID:???
あ、ちなみにこれは秀丸エディタで
強調表示するためのものです(perl版)。
■ このスレッドは過去ログ倉庫に格納されています