トップページ⇒php
986コメント301KB

正規表現道場@2ch

■ このスレッドは過去ログ倉庫に格納されています
0001ヽ(´▽`)ノ2001/07/26(木) 09:03ID:???
以外と毛嫌いして居る人も多そうな正規表現、
でもperlを使いのなす上で避けて通れない道だったりするかもです。
そこで、スクラップブック的に目に止まったカッコイイ正規表現を
書き留めておこうと言うスレッドです。
質問する時は言語と、得たい結果をなるべく詳しく書いてね。

取り合えず僕が知ってる有用なリンクです。
http://www.din.or.jp/~ohzaki/perl.htm
http://www.kt.rim.or.jp/~kbk/regex/regex.html

もっとイイ(・∀・) リンクは>>2-10さん辺りが書いてくれるカモ・・・・
0762nobodyさん02/10/21 13:17ID:???
>>754
そのコードは無限ループに陥る可能性が・・・
0763nobodyさん02/10/21 14:31ID:+QmxDt3y
他は大丈夫なのに、
何故か全角のスラッシュだけが置き換えされません・・
なんででしょうか?
$_ =~ s////g;

これでいいんですよね?
0764nobodyさん02/10/21 15:06ID:???
ほら見ろ、どこにも欠陥がないじゃねーか。
>>763
まず、lintで正しいhtmlかどうか確認しましょう。
>>762
ちなみに、あんたの予測ではどういう時に無限ループに陥る?
>>761
tbodyでtd、thと同じ行で共存しないでしょ。
$flg==1のとき(その行にtdかthがある場合)しか出力してないから
tbodyは無視していいのです。<\/*tfoot>の削除も実は不要だった。
>>760
<\/*thread>ってなってるでしょ。閉じはあってもあくても対応できるよ。
だれも書いてないことは、<tr>...</tr>の行が一行毎に改行されてない
のにかけたら、まったくだめだよってこと。その前処理を付ければ、
すばらーしスクリプトだな。

0765nobodyさん02/10/21 15:49ID:???
>>760
おっとうっかりしてた。
</*thead>とかじゃなくて、tr,td,thか。
それが閉じてないとやばいね。多分、lintには叱られるhtmlの書き方
だろうけど。それに対処するには、td,thのばやいは、次のtd,thか、改行まで、
trはもともと削除しちゃってるんだから関係ないと。
だから、上のスクリプトに
s#</t[dh]>#(</t[dh]>|<t[dh]>|$)#g;
すればいいっつことだな。
0766nobodyたん02/10/21 18:17ID:???
>>717
乗り遅れたが...

while(<>){
s/(.*?)[\r\n]*$/$1."\t".<>/es;
print;
}

ってのはどう?
0767nobodyさん02/10/21 23:29ID:pPxXD5oZ
恐ろしく厨な質問で恐縮なのですが・・・
一文字前が改行以外の「,」を検索することは
正規表現で出来るのでしょうか?
VBScriptの正規表現オブジェクトを使ってます。
[^\t\n],
だと改行が前に無い「,」とその一個前が取れてしまって・・・。
重ね重ね厨ですみません。。
0768nobodyさん02/10/21 23:31ID:???
あ、上の [^\r\n], です。すみません・・・。(鬱
0769主婦のサークルで〜す02/10/21 23:55ID:Ah6hwMht
ほんの少し刺激を求めてる主婦のサークルを作りました!
私たち主婦が楽しめる安全でちょっとトキメキのある出会を求めて
只今男性会員を募集中です!! 女性会員も募集(^○^)/"
http://f-cc.com/~tokimail/
077076202/10/22 00:35ID:???
>>764
以下の2行のごく単純なテーブルで実行してみれば?

<table><tr><td
bgcolor="White">hoge</td></tr></table>

あと、念のために聞くけどCSVって知ってる?
0771nobodyさん02/10/22 02:45ID:???
>>766

これって改造して、3列バージョン作れますか?
0772nobodyさん02/10/22 05:13ID:???
>>764
ちゃんと人の書いてること読んでから書き込め。
<tr>...</tr>の行が1行ごとに改行されてるtableが前提だ。
前処理もすぐに書けるが書いてないといってる。
お前のおかげで貴重な資源が無駄になった。もう2chには来るな。
おまえはCSVに何種類かあるか知ってるのか?漏れの出したの何ていう
名前のCSV? Kで始まるよ。
そういうのが分かってる奴しか相手にしないからお前は早く氏ね。
0773nobodyさん02/10/22 05:14ID:xIeaXQaj
>>760じゃなくて>>770だった。
あまりアフォだから晒しアゲ

0774nobodyさん02/10/22 07:58ID:???
>>772
まーまーおちけつ。
故意にせよ抜けてたにせよ、問題を含んでるのは確かなんだから、
より実用的なコードに仕上げた方が建設的ってもんでないかい?
0775nobodyさん02/10/22 10:53ID:???
とりあえず
<table>
<thead><tr><th>1</th><th>2</th><th>3</th></tr></thead>
<tfoot><tr><th>4</th><th>5</th><th>6</th></tr></tfoot>
<tbody>
<tr><td>7</td><td>8</td><td>9</td></tr>
<tr><td>A</td><td>B</td><td>C</td></tr>
<tr><td>D</td><td>E</td><td>F</td></tr>
</tbody>
</table>
の表示は
1 2 3
7 8 9
A B C
D E F
4 5 6
になるのでよろしく
0776nobodyさん02/10/22 11:51ID:???
糞ソース晒しあげ

while(<>) {
chomp;
$flg = 0;
$col = 0;
$line = $_;
$line =~ s/(<\/*thead>|<\/*tfoot>)//gi;
$line =~ s|</*tr.*?>||gi;
for $i (0 .. $#row_max) {
undef $row_data[$i] if $. > $row_max[$i];
}
while($line =~ /<(td|th)/) {
$flg = 1;
$col++;
$line = "$'$row_data[$col]$&$`";
if ($line =~ s|<t[dh][^<]+?rowspan.+?(\d+).+?>(.*?)</t[dh]>|"\",\"" . $2 . " (row: " . $1 . ")"|ei) {
$row_data[$col] = "<td>$2 (row: $1)</td>";
$row_max[$col] = $. + $1;
} elsif ($line =~ s|<t[dh][^<]+?colspan.+?(\d+).+?>(.*?)</t[dh]>|("\",\"" . $2 . " (cols: " . $1 . ")") x $1|ei) {
1;
} else {
$line =~ s|<t[dh][^<]*?>(.*?)</t[dh]>|","$1|i;
}
}
print "$line\",\"\n" if $flg == 1;
}
0777nobodyさん02/10/22 12:04ID:???
糞ソースのコピペはいいからまともなのを貼れ
0778nobodyさん02/10/22 13:28ID:???
>>775
やっぱり、CSVにはスペース区切りしかないと思ってたのか。
教えといてやる。スペース区切り、タブ区切り、コンマ区切り、K3形式...
おまえみたいなうすまぬけな変換だと
<tr><td>おまえは馬鹿 糞馬鹿</td><td> お前はアフォ 大アフォ</td></tr>
<tr><td>おいらはK3</td><td>他にどんな形式あるか知ってるか? 何も知らなきゃ黙ってろ</td></tr>
は、
おまえは馬鹿 糞馬鹿 お前はアフォ 大アフォ
おいらはK3他にどんな形式あるか知ってるか? 何も知らなきゃ黙ってろ
こんなんなっちゃって、桁が合わなくなって使いみちないよ。
おまえの単純なデータを漏れのすばらーしスクリプトで変換するとこうなる。
","1","2","3","
","4","5","6","
","7","8","9","
","A","B","C","
","D","E","F","
どこにいちゃもん付けたいんだ。

0779nobodyさん02/10/22 13:55ID:???
全員落ち着け。

>>778
775は一例でスペース区切り上げただけかもしらんだろ。

そもそもnobodyばっかで訳わかんねぇよ。
議論したいならトリップつけるか、自分が書き込みした最初の記事の番号ぐらい名乗れよ。

>>763 なんかtableとかCSVとかと何も関係なく質問しただけかもしれんのに、HTML-lintとか
ワケワカな答えされてるし。

傍から見てウザ過ぎ。

>>763
$_ =~s/\Q/\E//g;
って\Qと\EでくくればOK。
0780754=77802/10/22 14:13ID:???
>>779
あんたは喧嘩両成敗みたいなことやってるが、明らかに
悪いやつは、何の欠陥を指摘もできないで、漏れのスクリ
けち付けた>>757、>>775。
>>776は、すばーらしスクリをさらしてくれてありが�d。
「>>754はすばらーし」、だけでよかった。>>776も考えて
みりゃ、ネットのくずだ。早く逝け。


0781nobodyさん02/10/22 14:24ID:???
>>763 へのフォローは無しか。
そうやって熱くなって他の人間にまで迷惑を掛ける。
いくらお前から見て>>757、>>775が悪でも、傍から見たら一括りにしてウザイんだよ。

そこんトコ分かってくれ。
0782754=77802/10/22 14:26ID:X4lK8otn
>>775は、糞DOSでやってるんじゃないか。
漏れは自宅のLINUXでやってた。ほんで、>>778は、会社の
Solarisでやった。ちょっと気になって、winでやったら、
こうなった。
","1","2","3
","4","5","6
","7","8","9
","A","B","C
","D","E","F
つまり、\x0d\x0aの改行コードがchompでは1個しか取れなくて、
print "$line\",\"\n" if $flg == 1;
で後ろに付くべき","が消えている。付いてるんだけど表示されない。
もう少し、修行を積むことだな。
0783nobodyさん02/10/22 14:26ID:???
あ、781=779な。
0784754=77802/10/22 14:44ID:???
>>781
<table border="1">
<tr><td>おお</td><td>いい</td><td>うう</td><td>ええ</td><td>おお</td></tr>
</table>
は、
┌──┬──┬──┬─────┬─────┐
│おお│いい│うう│ええ</td>│おお</td>│
└──┴──┴──┴─────┴─────┘
になっちゃうけど?
それとも、漏れにhtml2csvじゃなくって、html-lint書けって言うわけ?
まったく別の質問だと思ってたけど?
ちなみに、
$_ =~ s////g;
eucではperlで問題無いけど、sjisでは、/が815Eだから、1バイト文字と重なるね。
81の00と5Eの^に。で、エスケープした方がいい?


0785754=77802/10/22 14:48ID:???
>>781
そうそう、sjisで日本語やってんなら、jperlにしたら、こいうこと
気にしなくていいんじゃない、って書こうと思ったんだ。
078677902/10/22 15:53ID:???
>>784
へぇ、>>763はHTMLの話なんだ。どこからその毒電波でたの?
>>785は同意だけど。

あと君のスクリプトサラッと見てみたけど、colspanとrowspanの2つとも指定されたtdを含む場合
(<td colspan="2" rowspan="2">ほげ</td>ってみたいなの)、問題あるような気がするけど。
0787754=77802/10/22 16:34ID:???
>>786
それは考えてませんでした。うすうす気づいてたけど。
そういうまともな批判を待ってました。ありが�d。
<tr>...</tr>の途中で改行されてるデータと、solspan、rowspanが両方
指定されてるデータに対応したのを作ってみます。比較的すいてるので、
この前は上げたけど、不評なので、上げるかどうか分かりません。
0788nobodyさん02/10/22 17:48ID:???
" や , はエスケープしなくていいの?
0789nobodyさん02/10/22 17:53ID:???
・多分正常なHTMLならOK
・多分改行も関係ない
・多分バグある
・多分滅茶苦茶叩かれるw

http://homepage3.nifty.com/~moemoe/table2csv.pl.txt
0790nobodyさん02/10/22 17:54ID:???
>>788
いいよ。
0791nobodyさん02/10/22 18:30ID:???
>>789
いいねこれ。もらったぜサンキュー!
079278902/10/23 01:50ID:???
イイですか?
自分で書いといて何だがもっとコンパクトに書けそうな気がしたんで
添削キボンなんだが。
ってココまで行くと正規表現の範囲でも無いか。sage
0793754=77802/10/23 02:53ID:???
ここは正規道場だからね。漏れはほとんどスカラでやって正規表現の
使い方を示した。rowspanだけは難しかったので配列をつかっちゃった。
>>754は、10分か20分で作ったので、さっき改行とcolspan、rowspanに
対応したのを配列なんか使わずに書いたが・・・
Perlのスクリプトを競うのなら「スクリプト改造工房」、「Perl
初心者コーナー」あたりにどうぞ。


079477502/10/23 03:05ID:???
ええと、言いたかったのは
4 5 6
が2番目ではなくて最後になるってことで
区切りなんてどうでもよかったんでIEの表示結果を
コピペしただけだったんですが
0795754=77802/10/23 03:29ID:???
>>794
漏れの実行結果2回も貼り付けたが、なってないじゃん。
お前の実行結果を貼り付けてみる。捏造するのに時間かかるだろ。
0796754=77802/10/23 03:31ID:???
なるほど、そいうことか。また改造だ。あんが�d。
0797nobodyさん02/10/23 10:13ID:???
激しくがいしゅつだと思うんですけど、メールアドレスの正規表現です。
perlメモを見ましたが初級者にはどう考えても理解できません。
別に理解しなくてもサブルーチンとして貼り付ければいいだけかもしれないんですが、
ある程度何をやっているかわからないとやっぱり気分が悪いです。
で、皆さんが普段利用しているメールアドレスチェック正規表現を教えていただければこれ幸いです。
0798ぶっちー02/10/23 10:36ID:IaWkOnQn
秀麻呂エディタで「1KG」とか「999KG」の数字3ケタでKG表示している
文字列を「 [999KG] 」のように[]で囲みたくて正規表現を使って置き換え
してるんですがうまくいきません・・・

「オレ様,男,25才,189cm,98KG,12%」
みたいなカンジでカンマで区切ってある行が2000行くらいです。
この中の体重部分だけを[]で囲みたいんデス(泣;
0799nobodyさん02/10/23 11:00ID:???
>>798
これはどうよ
$a =~ /,(\d*KG),/;
$a =~ s/(\d*KG)/[$1]/ig; 
080078902/10/23 11:13ID:???
ちょと修正
・改行関係のバグ
・余計なタグの削除
・その他
スレ違いなのでもうココまで。

>>794
漏れのは多分大丈夫かと。

>>797
$mail =~/^[0-9a-zA-Z_\.-]+@([a-zA-Z0-9][a-zA-Z0-9_-]*\.)+[a-zA-Z]{2,}$/;

>>798
v.3.00以降のみ対応。
・検索:,\f[0-9]*KG\f
・置換:,[\1]
,が付いてるのは名前のトコにも数字KGってくる可能性があるので。
0801nobody02/10/23 11:23ID:???
>>798
正規表現道場だから、
s/((.*?,){4})(.*?),/$1\[$3\],/;
しかし、普通は、配列を使って、
split/,/;
print "$_[0],$_[1],$_[2],$_[3],[$_[4]],$_[5]";
0802ぶっちー02/10/23 11:34ID:IaWkOnQn
>>789サマ

神!できました!
どうもありがとうございましたヽ(´∀`)ノ

「タグ付き正規表現」ってヤツですね。
ま、それ知ってても自分でできたとは思えませんが・・・
0803ぶっちー02/10/23 11:41ID:IaWkOnQn
>>800サマ・・・でございました(汗;

>>798サマ
>>801サマ

PG上でのマッチングじゃなくて秀丸で成形してから
SQLに渡そうと腐心しておりマスタ。いずれにせよ
ソース上で有用な構文、ありがとうございました!
0804nobodyさん02/10/23 12:17ID:???
なんか自分の考えが正しいと思いこんで他人に押し付けるスレはここですか?
0805nobodyたん02/10/23 12:49ID:???
Email::Valid 使え。
と思ったり。

変に不完全なチェックするよりマシ。
0806nobodyさん02/10/23 13:28ID:???
>>804
お前のことか?
0807nobodyさん02/10/23 17:24ID:???
まあいくらチェックしても[email protected]とか貼られると
どうしようもないわけだが
0808nobodyさん02/10/23 17:57ID:???
汚染チェックだけしとけばいいって事ですか。
0809nobodyさん02/10/23 18:03ID:???
>>808
どうせだからそのドメインがホントにあるか&メル鯖はあるか迄見とけ。
0810nobodyさん02/10/23 20:28ID:???
「文字を含まない」→[^a]*
みたいに出来ますが、

「ある文字列を含まない」ってどうやるんですか?
0811nobodyたん02/10/23 21:06ID:???
正規表現では表現不可能です。というのが教科書的な回答。
(バックトラックしつつ、) 前から順番にマッチさせていって、最後まで行っ
たら受理されるってのが正規表現だから。
でも、perl の拡張正規表現を使えば出来てしまうのが気持悪いところ。

print "ok\n" if(/^(?!.*xyz)/); # "xyz" が入っていなければ表示される。

先頭の後ろに「任意の個数の文字に "xyz" が続く文字列」が来ないものにマッ
チ。= "xyz" を含まない文字列にマッチ。
0812nobodyさん02/10/24 00:07ID:???
つーかさ

print "ねーよ" if ($str !~/xyz/);

とか

print "ねーよ" unless ($str =~/xyz/);

じゃ問題あんの?
0813nobodyたん02/10/24 00:19ID:???
無いよ。
もちろん、普通はそういうコード書く。
0814りり02/10/24 10:25ID:iH2BcaJh
下のようなフォーマットの日付データを年・月・日に分解するには
どうすればよいですか?

2002.9.1
2002.10.1
2002.11.31

また、与えられた文字列が日付のフォーマットではない場合のチェックは
どうすればいいですか?
教えてください。
0815nobodyさん02/10/24 11:39ID:???
# 2002.09.01はNG、日付の妥当性もある程度チェック
die "日付じゃねーぞ" unless ($date =~/^(\d{,4})\.(1[0-2]|[1-9])\.(3[0-1]|[12][0-9]|[1-9])$/);
$year = $1; $month = $2; $day = $3;

# 2002.09.01もOK、日付の妥当性もある程度チェック
die "日付じゃねーぞ" unless ($date =~/^(\d{,4})\.(1[0-2]|0?[1-9])\.(3[0-1]|[0-2]?[0-9])$/);
$year = $1; $month = $2; $day = $3;

# うるう年とかあるし後でチェックするから取りあえず数字よこせ
die "日付じゃねーぞ" unless ($date =~/^(\d+)\.(\d+)\.(\d+)$/);
$year = $1; $month = $2; $day = $3;
0816nobodyさん02/10/24 18:21ID:???
splitした方が速そうだ…
0817nobodyさん02/10/24 20:29ID:???
ちょっとだけ、おじゃましまーす。

どーでもいいと言わないで下さいね。

=~
ってすごく打ちやすいですよね!
!~
ってメチャ打ちにくいですよね?

皆さん、
!~
をあまり打たないようにコーディングを工夫した方が、
指疲れなくて体に健康ですね。

失礼しましたー
0818nobodyたん02/10/25 02:51ID:???
私は
if(not $hoge =~ /REGEX/) { ... }
if(not $hoge = 123) { ... }
if(not $hoge eq "hage") { ... }
としている。

まぁ、とりあえず好きなように書けってことで。
0819nobodyさん02/10/25 09:06ID:???
>>817
それは正規表現じゃないのでPerlスレでやってくれ。
0820nobodyさん02/10/25 12:20ID:???
>>818
わざわざ

if(not $hoge = 123) { ... }

と書く理由がわからん。以下のように書きなさい。

if(0){ ... }
0821声域表現02/10/25 13:13ID:fEObcI9/
ちょいと質問。
ログファイルをlog.txtで保存してあります。
中身はこんな感じです。

番号,住所,電話,名前

で、フォームに番号を入力させて送信。
次のページで名前が出てくるって仕様です。

正規表現を用いてlog.txtの番号と同じ行にある名前を持ってきて表示させるには
どうしたらいいのでしょうか?
糞素人丸出しでスマソ、前後に上司でテンパーイ
0822nobodyさん02/10/25 13:53ID:???
$bango = $in{"bango"};
print $2 if /$bango,{.+*,){2}(.+)/;
とか。
0823nobodyさん02/10/25 13:55ID:???
うっ、/^$bango,{.+*,){2}(.+)/;だった。
0824nobodyさん02/10/25 13:55ID:???
うっ、/$bango,{.*,){2}(.+)/;だった。
0825nobodyさん02/10/25 13:59ID:???
うっ、/^$bango,{.*?,){2}(.+)/;だった。
# 前のレスと同じバイトだと書き込めないのか。2重書きこですかだって。
0826302/10/25 15:34ID:???
2002.10.19(土)10-15h  2002仙台市下水道フェア  (雨天決行)

稲垣達也ライブ 「水の音、風の音、光の音」(11;55〜 14:15〜)

場所:勾当台公園 連絡先:仙台市下水道局022-214-8813

2002.10.19(土) 大沢農学校ケナフ学科 (4) 作品づくり(さをり織 など)

場所:大沢市民センター  連絡先:大沢市民センター

2002.10.19(土)サイカチネイチャークラブ観察会 

場所:国立南蔵王青少年野営場 連絡先:サイカチネイチャークラブ

0827302/10/25 15:36ID:???
3です。



2002.10.19(土)10-15h  2002仙台市下水道フェア  (雨天決行)
稲垣達也ライブ 「水の音、風の音、光の音」(11;55〜 14:15〜)
場所:勾当台公園 連絡先:仙台市下水道局022-214-8813

2002.10.19(土) 大沢農学校ケナフ学科 (4) 作品づくり(さをり織 など)
場所:大沢市民センター  連絡先:大沢市民センター

2002.10.19(土)サイカチネイチャークラブ観察会 
場所:国立南蔵王青少年野営場 連絡先:サイカチネイチャークラブ

のようにするにはどうすればいいでしょうか?

正規表現で、
2002.10.19
などの日付にマッチさせるのはわかるのですが、複数行にわたる処理って難しいですね。

0828nobodyさん02/10/25 15:55ID:???
レコード区切りを除いて空行を削除したいってこと?
s/\n\n(?!\d+\.\d+\.\d+)/\n/gs;
0829nobodyさん02/10/25 16:12ID:???
>>826 - >>827
何やりたいか、はっきり書け、ヴォケが
0830声域表現02/10/25 16:15ID:fEObcI9/
レスありがとうございます。
具体的に書きます。

log.txtの中身はこんな感じです。
0001  東京  国語  【山田】
0002  千葉  数学  【佐藤】
0003  埼玉  物理  【金子】

番号、住所、科目、名前が入っています。
仕様は番号を打ち込むとその行にある名前が返ってきます。
例えば0001と番号を打ち込み送信すると次のページで
「山田」と出てくるのです。

自分がイメージしている方法ではlog.txtに名前を書き込むときに
【】の括弧で挟んで名前を書き込み、呼び出してくるときに
「"番号(0001)"の列の【】(【山田】)で囲まれた部分を持って来い」
と言う、命令をしたいのです。
こうする事により”名前”がどこにあっても番号と同じ列の【】でくくられた中を
参照するので楽だと思ったのです、感覚的にですが。
これって正規表現で可能なんですか?
0831nobodyさん02/10/25 16:21ID:???
わざわざ難しくしてどうするんだ阿呆が
0832声域表現02/10/25 16:24ID:fEObcI9/
では【】を使わないでやるにはどうすればいいのでしょうか?
名前は行の一番最後にあると仮定すると。
0833nobodyさん02/10/25 16:50ID:???
>>822-825は見たのか?
そもそも>>829は貴様へのレスじゃないぞ間抜け
0834声域表現02/10/25 17:05ID:fEObcI9/
>>833
>>829が自分へのレスじゃないことぐらいわかります。
その前に貴方は一体なんなのですか?
単に煽りの気がします。
0835nobodyさん02/10/25 18:00ID:???
http://pc.2ch.net/test/read.cgi/php/996105815/830
マルチうざ
0836 ◆ZD/EuPncnQ 02/10/25 18:02ID:???

1 東京 国語 山田
2 千葉 数学 佐藤
3 埼玉 物理 金子


open(FILE,"./log.txt");
@hoge=<FILE>;
close FILE;

foreach (@hoge){
@temp=split(/\s/,"$_");
($hage,$hige)=("$temp[0]","$temp[3]");
$word{$hage}="$hige";
}

print "number :";
chomp($a=<stdin>);
print "$word{$a}\n";
0837声域表現02/10/25 18:12ID:fEObcI9/
>>836
ありがとうございます。
これを元にがんばってみたいと思います。
0838nobodyさん02/10/25 21:17ID:I2JNYDvh
おとなの玩具激安販売!
なんとピンクローター300円から♪
マニアック商品などその他いろいろあります!
http://www.king-one.com
0839827 02/10/25 22:48ID:???
>>829
ああ、やりたいことが確かに判りませんね。
迂闊でした。


改めて、質問いたします。

レコード区切りとなるものが存在せず、
2002.10.19
などの日付にマッチさせ、その前の行は空白を残して、
それ以外の空白を消すということです。

つまり、
\n\n\d\d\d\d\.\d+\.\d+.*
のようなものが区切りのキーになると思います。



0840nobodyさん02/10/26 08:59ID:???
だから>>828に書いたんだが。
直後に書かれた答えを無視して再質問するのがはやってますか?
0841Weasel02/10/26 18:30ID:lT7ooPWd
Apacheのログ(Combined)を正規表現しようとして
いるのですが、やり方がわかりません。

> 127.0.0.1 - - [10/Oct/2000:13:55:36 -0700]
> "GET /apache_pb.gif HTTP/1.0" 200 2326
> "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"

というログフォーマットを
・IPアドレス
・日付
・時間
・ファイル
・処理コード
・バイト数
・参照元
・エージェント

でCSVにしたいのですが・・・

だれか教えてください。
0842nobodyさん02/10/26 18:59ID:???
CSVって何か知ってる?
0843nobodyさん02/10/26 19:54ID:lT7ooPWd
>842

CSVってカンマで区切ったフォーマットのことですよね。
Apacheのログは基本的にスペース区切りなのですが、
単にスペースをカンマ(,)に置き換えると、GET /index.html
の中のスペースが区切られたり、いらない「”」が入ったり、
と困っているわけです。また、日付と時間を別のフィールド
にしたいので、正規表現を利用してきちんと指定したいのです。

今は
 1 行を読み込む
 2 - - [ を削除
 3 日付の「2000:」を「2002,」に変換する
 4 -9000] を削除
 5 「"GET 」を削除
 6 ダブルクォーテーションを削除
した上でスペースをカンマに変えてCSVにしています。

これを世紀表現を利用して、もっとスマートにしたいのです。

よろしくお願いいたします。
 
0844nobodyたん02/10/26 20:39ID:???
my($remote, $ident, $user, $datetime, $req, $status, $size, $referer, $ua)
= m{(\S*) \s+ # remote
(\S*) \s+ # ident
(\S*) \s+ # user
\[(.*?)\] \s+ # datetime
"(.*?)" \s+ # request line
(\S*) \s+ # status
(\S*) \s+ # size
"(.*?)" \s+ # referer
"(.*?)" # user agent
}x;

とでもした後、適当に変形すれば良いだろ。
0845Weasel02/10/26 20:47ID:lT7ooPWd
>>844

ありがとうございます。早速試してみます。
0846nobodyさん02/10/26 22:48ID:???
以前から、ずーと欲しいツールで、
正規表現だけで解決できるかどうかわかりませんが、
あるディレクトリにcsvファイルが
data01.csv
data02.csv
……
data10.csv
のように存在しています。
これを
perlなどで処理したい場合、これらのデータをファイル読み取りのところで、
配列の配列の配列やハッシュのハッシュのハッシュ
という3次元データー構造に変換しなければ、その後のプログラミング
が煩雑になりそうで、いままで、ずーと避けてきました。

厨な私は、普段はこれをエクセルで処理してるんですが、
いっそのこと正規表現で処理してしまえないでしょうか?

なにかアドバイスありますか?
0847nobodyさん02/10/27 00:42ID:???
>>846
で、どう処理したいの? 肝心な部分を書いてくれないとなんとも言えないよ
0848Weasel02/10/27 00:52ID:5TH4jHN5
>>846

 1 ディレクトリ下のファイル名を<*>で取得
 2 ファイルを開く
 3 tempファイルにファイル名と一緒に一行ずつ書き出す
 4 ファイルの数だけ2と3を繰り返す
 5 まとまったtempファイルを処理する

てな感じではどうでしょうか? とは言うもののdata01〜10.csvの
違いがわからないのですが?
0849Weasel02/10/27 01:07ID:5TH4jHN5
>>844

すみません。これPerlでしょうか?
 m{ ... }x;
という書式の意味がわからないです。読み込んだ
ログファイルはどの変数に格納すればよろしいの
でしょうか?

大変あつかましくて恐縮ですが、何卒ご教授お願い
します。

0850nobodyさん02/10/27 02:25ID:???
やりたいこと→perl式
は質問してもしかたないけど
perl式→説明
は「おしえて君」
ですよ。自分で調べられるでしょう。やりたいこと→perl式
は質問していいけど、
perl式→説明
は自分で調べられるでしょう。
0851nobodyさん02/10/27 02:45ID:5TH4jHN5
>>850

失礼しました。会社にラクダ本があるので、
月曜日に調べてみます。
0852nobodyさん02/10/27 03:15ID:???
844じゃないけど。
 /xモディファイアは、正規表現の中にスペースとかコメントが
入るのを許すもの。m{...}は、デリミタを(デフォルトの"/pat/"
だと"/"をエスケープしなきゃいけなくなるので)"{pat}"にするよ、
とういうことでつな。

>読み込んだログファイルはどの変数に格納すればよろしいの
>でしょうか?
 普通に読み込めば?
open LOG, "hoge.log";
open OUT, ">fuga.csv";
while(<LOG>){
     #844さんのコード
     #その他必要な処理
     
     print OUT "$remote, $ident, $user, ・・・\n";
}
close OUT;
close LOG;
 みたいな感じで。
0853nobodyさん02/10/27 08:54ID:???
>>73
がなぜ
ドラゴンクエスト?
0854Weasel02/10/28 02:01ID:pNQg1CBu
>844
>852

情報ありがとうございます。これってPerlの省略形だった
のですね。


1 変数の記述省略
  while (<LOG>) {
   print;
  }
  
  という指定は
  
  while ($xx = <IN>) {
   print $xx;
  }
  
  という指定と同じことなのですね。私は常に変数を記述していた
  (もっというと、配列に読み込んでforeachを使用していた)ので
  わからなかったです。


2 m{ ... }x; について
  これが正規表現だということに気づきませんでした。
  私はいつも
   $ =~ s#abc#def#x
  という形で利用していたので、上記のような指定ができることを
  知りませんでした。

もっと勉強します。本当にありがとうございました。
0855nobodyさん02/10/28 09:19ID:???
すいません。初心者なんですが、
正規表現にて日本語以外、ってどのように指定したらいいんでしょうか。
英字、数字、空白文字はOKで、日本語のみだめ。
jcodeとかつかわないとムリなんでしょうか?
0856nobodyさん02/10/28 13:02ID:???
[a-zA-Z0-9 ]
085782702/10/28 15:19ID:???
828さんどうもありがとうございました。

返事が遅くなりました。
0858nobodyさん02/11/02 05:32ID:I/qwWelh
/aaa::bbb
/bbb
/aaa::bbb/ddd
/bbb/ccc::ddd

つまり
/aaa::bbb
/bbb
等の繰り返し
# aaa:: は省略可能です。

などにマッチさせようとしてるんですけど駄目っす。
助けてください。↓今のとこ、こんな感じ

(/([^:/]+::)?[^:/]+)+
かなり的外れっぽいですが(汗
0859nobodyさん02/11/02 13:39ID:???
/^(?:\/(?:[a-z]+::)?[a-z]+)+$/;
086085902/11/02 14:31ID:???
●/aaa::bbb::ccc/ddd のパターンを許すなら

/^(?:\/(?:[a-z]+::)*[a-z]+)+$/;

● / と : 以外の文字が[a-zA-Z_]なら
/^(?:\/(?:\w+::)*\w+)+$/;
086185802/11/02 16:22ID:I/qwWelh
さっそくありがとうございます >859

目的としているのは、>859見たいな奴ですが、
Invalid regular expressionとか出てしまいました(;_;
regex.cで(GREP?SED相当?)最終的にできればいいんですが。

どうも
?:
のとこでコケテます。

ちなみに、
いいい::あああ/ううう
とかも可能にしたかったりします。

あああ、いいい、ううう
に入れられる文字は:と/以外といった感じで。
0862nobodyさん02/11/02 16:45ID:ywtiXWST
()で囲まれた文字列だけ

str1,str2,str3(str4,str5,str6)str7,str8,str9 なら str4,str5,str6 だけ

"," → "," と変換したいのですが、
どういう文にすればいいですか?

s/\(([^\)]+),([^\)]+)\)/\($1,$2\)/g;

を何回か繰り返すことで何とか済ました(本当か?)のですが、
まともなやり方を知りたくなりまして。
■ このスレッドは過去ログ倉庫に格納されています