アプリ版:「スタンプのみでお礼する」機能のリリースについて

以前こちらでおなじような質問をして回答いただいたのですが、どうしても理解できないので再度質問させていただきます。

フォームで名前や件名などを入力してもらい、その入力データをログファイルへ入れます。
ログファイルは以下のような感じのものが何行も続いています。
NAME=hoge&TITLE=tatoeba&NAKAMI=konnnakanji&LOCALTIME=20030127094224=
(LOCALTIMEだけは自動で入るようになっています。)

その後で、このログファイルから任意の行を取り出したいのですが、削除されることもあるため○行目という値では意図するものが出てこない可能性もあるので、
LOCALTIMEで検索をしたいのです。
20030127094224と入れた場合、ログファイルの○行目、と判定するようなことをしたいのです。

どのようにしたらいいのかさっぱりわかりません。
よろしくお願いします。

#perlです。

A 回答 (4件)

急いで書いたら一部訂正です。



## $nnは行をカウントする為に設定します
$nn=0;

## ログを1行ずつ読み込みます。行が存在する分、繰り返します。
foreach $line (@lines){

## 読み込んだ行を 「&」で区切り$NAME $TITLEなどに格納します。
($NAME,$TITLE,$NAKAMI,$LOCALTIME) = split(/&/,$line);

## $LOCALTIMEは そのままでは「LOCALTIME=」という文字を含んでいるので、10文字目から最後までの文字を$LOCALTIMEと設定し直します。
$LOCALTIME=substr $LOCALTIME,10;

## ちょっと訂正しました。もし検索ワードとLOCALTIMEが同じであれば、このループを抜け出します。
if($検索ワード eq $LOCALTIME){last;}

## 検索ワードとLOCALTIMEが違う場合は$nnに1を足します。
else{$nn++;}

##繰り返し部分を閉じます
}

ループを抜け出すのを忘れていたので 一部訂正して $nnに行数が入るようになりました。

あと$LOCALTIMEのすぐ後ろに改行があるので(ログの各行は改行されてますよね?) それを取り除かないとヒットしないかもしれません。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

ちょっと自分なりにアレンジしてみてこんな感じにしてみました。


print "Content-type:text/html\n\n";
open(FILE, "teian.log");
@logfile = <FILE>;
close(FILE);

#行をカウントするためのもの。
$i = 0;

@log = split(/&/,$logfile[$i]);

foreach (@log){
$log[$i] =~ s/\n$//;
@logs = split(/&/,$_);
#$logs[$i] =~ s/\n$//;
($key,$value) = split(/=/,$_);
$FORM{$key} = $value;
#$FORM{'LOCALTIME'}=substr('$FORM{'LOCALTIME'}',19); ##[$FORM{'LOCALTIME'}=の文字を除く
if($searchvalue eq $FORM{'LOCALTIME'}){
print "あってるよ。\n";
print "<FONT COLOR=BLUE>$FORM{'LOCALTIME'}</FONT>\n";
last;
}##あっていればループを抜ける
else {$i++;}
}

1番最初のログのLOCALTIMEで検索するときちんと「あってるよ」と出るのですが、2つ目、3つ目、となるとできません。
誤りのご指摘お願いします。

お礼日時:2003/01/30 14:53

自己流なので 回りくどいかもしれませんが



open(IN,".ログファイル")
@lines = <IN>;
close(IN);

$nn=0;
foreach $line (@lines){
($NAME,$TITLE,$NAKAMI,$LOCALTIME) = split(/&/,$line);
$LOCALTIME=substr $LOCALTIME,10; ##「LOCALTIME=」の文字を除く
if($検索ワード eq $LOCALTIME){$gyou=$nn;}
else{$nn++;}
}

これで何行目というのが $gyouに入るはずです
    • good
    • 0

> /^NAME=.+&LOCALTIME=[0-9]+=/


> はどのような意味でしょうか?

大雑把に言えば、「NAME=」から始まり、途中から「&LOCALTIME=」、直後にいくつかの数字、そして文字「=」を含む文字列に一致するパターンを表してます。
詳しい事は、Perlの書籍や正規表現についての書籍などをご覧ください。

スクリプトを大雑把に言えば、
・コマンドラインの第一引数を日付け指定とする検索パターンを作成。
・ログ配列を先頭から順に見てゆき、検索パターンに一致するものがあったら、結果変数に格納。
・結果変数の中身が空でなければ、検索にHitしたということで、それを表示、空なら見つからなかったと報告。
――ってところです。
正規表現引用演算子qr以外は、Ver.4のPerlでも動くようなスクリプトです。
正規表現を使わなくたって、index()とかでも検索部の条件判断は記述できますね。

キーワードで不明なのがありましたら、Perl付属のマニュアルperlfuncかperlopをご覧下さい。
またサンプルスクリプトを実行してみて、各変数の内容をprintで出力してみたり、正規表現パターンを変更したら挙動がどう変わるかを実験してみると、理解が早まるかと思います。
    • good
    • 0

> NAME=hoge&TITLE=tatoeba&NAKAMI=konnnakanji&LOCALTIME=20030127094224=


この形式で、LOCALTIMEで検索するなら、

/^NAME=.+&LOCALTIME=[0-9]+=/

みたいな、正規表現で引っ掛けられるかと。

以下は実験。Mac OS X 10.2.3+perl v5.6.0で試してます:

% cat a.pl
$arg = $ARGV[0];
@Log = <DATA>;

$find_pattern = qr|^NAME=.+&LOCALTIME=${arg}\d*=|;

$find_line = ''; $find_lino = $lino = 0;
for ( @Log ){ $lino++;
next unless $_ =~ $find_pattern;
$find_line = $_; $find_lino = $lino; last;
}

if ( $find_line ne '' ){
print $find_lino, ': ', $find_line, "\n";
} else {
print $arg, " not found.\n";
}
__END__
NAME=hoge&TITLE=tatoeba&NAKAMI=konnnakanji&LOCALTIME=20030127094224=
NAME=hoge&TITLE=test&NAKAMI=konnnakanji&LOCALTIME=20021107095959=

% perl a.pl 200301
1: NAME=hoge&TITLE=tatoeba&NAKAMI=konnnakanji&LOCALTIME=20030127094224=
% perl a.pl 200201
200201 not found.

削除されたものを除外するには、ループの中で$linoをインクリメントする前に、スキップさせるとか。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

せっかく回答いただいたのですが、私には理解ができません…。

まず

/^NAME=.+&LOCALTIME=[0-9]+=/
はどのような意味でしょうか?

その後のコードもわかりません。
申し訳ございませんが、解説いただけるとありがたいです。

よろしくお願いします。

お礼日時:2003/01/27 11:03

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