プロが教える店舗&オフィスのセキュリティ対策術

Perlの正規表現についての質問です。
例)
899 YES Alt 0 0.000 pps 2.000 pps 4.000 pps 0
2 YES Alt 0 1.222 (space)-0.100 (space)3.000(space)0
103 NO Alt 0 3.333 % 0.000 % 0.000 % 0
               ^^^^^
=====抜粋========================================
if($_ = ~ / Alt+(\s+)+0+(\s+)+(\S+)+(\s+)+(\S+)+(\s+)+(\S+)+(\s+)+(\S+)+(\s+)+(\S+)+(\s+)+(\S+)+(\s+)+(\S+){
print OUT "\n$5,";
=================================================

上記のような文字列があるとして"^^^^^"だけを抜き出したい場合の正規表現はどのようにすればよろしいのでしょうか?
考えたif文では当たり前ですが2番目の(-0.100)が抜き出せません。また、検索できた順に抜き出し、出力したいので
if文を二つ書くのは避けたいです。
どなたか教示ください。


宜しくお願い致します。

A 回答 (5件)

>もうひとつ教えてほしいのですけど、抜き出した値が200.000や-12.000



整数部分が一桁に限らないということですね。

\d\.\d+
-?\d\.\d+

の \. の前の部分が整数部分の数字になります。
現状でそこは \d つまり数字一つしか想定していないのでここを
複数の数字を受け付けるようにすればOKです。
つまり、
\d+\.\d+
もしくは
\d*\.\d+
のようになります。これは、前者は整数部に必ず数字がなければいけませんが
後者は .1828459 のようなものも受け付けます。
    • good
    • 0
この回答へのお礼

ありがとうございました。
抜き出せました。
このたびは、不快な気持にさせたにも関わらず、
ご親切にアドバイスいただきまして、本当に助かりました。

お礼日時:2008/12/09 00:02

> 5.8に書き換えて、実行してみまたところ、マッチングエラーが出ました。



if($_ =~ /Alt \s+ \d+ \s+ (\d\.\d+) [^\d-]+ (-?\d\.\d+))/;
print OUT "$1," ;

これはわたしの例示した正規表現がどうこうじゃなくて、質問者さんのif文の書き方が悪いだけですけど
なぜにそこまで面倒見なければならないのですか?

if($_ =~ /Alt \s+ \d+ \s+ (\d\.\d+) [^\d-]+ (-?\d\.\d+)/x) {
print OUT "$1," ;
}

この回答への補足

sakusaker7様
>これはわたしの例示した正規表現がどうこうじゃなくて、質問者さんのif文の書き方が悪いだけですけど
>なぜにそこまで面倒見なければならないのですか?
私のif文がまずいのはわかった上でアドバイスを頂きたかったのです。文章の書き方よくなかったようです。すいません。

もうひとつ教えてほしいのですけど、抜き出した値が200.000や-12.000
の際も抜き出せるようにするにはどのような正規表現にすればよろしいのでしょうか?
何卒、よろしくお願いします。

補足日時:2008/12/08 21:02
    • good
    • 0

5.10固有の機能(ここでは say)を使うために、これまた 5.10固有の featureを使っています。


5.8とかでやるのなら、sayを printに置き換えてください(末尾の改行は自分で付加)。

あるいは Perl6::say モジュールを入れてもよいです。

この回答への補足

アドバイスありがとうございます。
5.8に書き換えて、実行してみまたところ、マッチングエラーが出ました。
Unmatched [ in regex; marked by <-- HERE in m//Alt \s+ \d+ \s+ (\d\.\d+) [^\d-]+ (-?\d\.\d+))

####################################################
#!/bin/perl

open(LOG,"<$ARGV[0]"); #FileOpen
open(OUT,">$ARGV[0].csv");
while (<LOG>) {
if($_ =~ /Alt \s+ \d+ \s+ (\d\.\d+) [^\d-]+ (-?\d\.\d+))/;
print OUT "$1," ;
}
}
close(OUT);

すみませんが再度アドバイスを頂きたく、よろしくお願いします。

補足日時:2008/12/08 08:28
    • good
    • 0

なんか頭が痛くなる正規表現ですね


何でもかんでも () で囲むから、どれが必要なパターンなのかわかりにくいし
(\s+)+
のようにカッコの中の最後が繰り返しで、外側にすぐまた繰り返しというのは
意地悪な入力を食わせたときにバックトラックの回数が爆発する可能性があるので
基本的には禁じ手です。

で、

899 YES Alt 0 0.000 pps 2.000 pps 4.000 pps 0
2 YES Alt 0 1.222 (space)-0.100 (space)3.000(space)0
103 NO Alt 0 3.333 % 0.000 % 0.000 % 0

から、
2.000
-0.100
0.000
を抜き出したいということと、(space)が一個以上のスペースだとすると

数値の部分の表現は多少修正するとしても

use strict;
use feature ':5.10';

while (<DATA>) {
chomp;
say;
/Alt \s+ \d+ \s+ (\d\.\d+) [^\d-]+ (-?\d\.\d+)/x;
say "$1 : $2";
}
__END__
899 YES Alt 0 0.000 pps 2.000 pps 4.000 pps 0
2 YES Alt 0 1.222 -0.100 3.000 0
103 NO Alt 0 3.333 % 0.000 % 0.000 % 0

こんな感じで取れるんじゃないでしょうか。
実行結果:
899 YES Alt 0 0.000 pps 2.000 pps 4.000 pps 0
0.000 : 2.000
2 YES Alt 0 1.222 -0.100 3.000 0
1.222 : -0.100
103 NO Alt 0 3.333 % 0.000 % 0.000 % 0
3.333 : 0.000

そもそも区切りがどうとか考えないで、数値の部分だけまとめて取り出せばいいような。

my @f = /(-?\d\.\d+)/xg;
say join(' : ', @f);

0.000 : 2.000 : 4.000
1.222 : -0.100 : 3.000
3.333 : 0.000 : 0.000

この回答への補足

sakusaker7さま
教えて頂いた記述を実行してみたのですが、
Can't locale feature.pm in @INC(@INC contains: C:/perl/lib C:/perl/site/lib .)
at test.pl line2 .
BEGIN failed--compilation aborted at test.pl line 2.
とエラーになります。
verの問題なんでしょうか?アドバイスをお願いします。

補足日時:2008/12/07 10:09
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
ご回答いただいた表現について、初心者の私には理解するには
難しい箇所もございますが、確認してみます。

お礼日時:2008/12/06 08:54

その (space) というのは何を表していますか?


各行の正確なフォーマットと「どこを取り出したいのか」を書いてもらえませんか?

この回答への補足

ご質問の件について、回答します。
sakusaker7様のご回答がそのままなのですが


899 YES Alt 0 0.000 pps   2.000  pps   4.000 pps    0
2  YES Alt 0 1.222 (space)-0.100 (space) 3.000(space) 0
103 NO Alt 0 3.333 %    0.000 % 0.000 %   0

から、
2.000
-0.100
0.000
を抜き出したいということ。
(space)が一個以上のスペース(空白)を意味します。
以上でございます。

補足日時:2008/12/06 08:34
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!