Perlコーディング初心者質問スレ Part 49
レス数が900を超えています。1000を超えると表示できなくなるよ。
0001nobodyさん
2006/05/31(水) 04:32:28ID:???【投稿する際の注意】
質問するときは内容をよく吟味してから投稿してください。
「コマンドの意味がわかんない」とかはマニュアル見ましょう。
回答者さんは何でも屋じゃありません。
1: 自分はこういう事がしたい。
2: それでこんな風にやってみたが・・・
3: こんなエラーが出て上手く行かなかった。
最低でも1と3が無いと誰も答えられないよ。
ソース貼る時は、全角スペースでインデント忘れずに。
良い回答は良い質問から。一緒に勉強しましょう。
過去ログやお勧めサイトは >>2-10
0839737
2006/06/22(木) 14:45:33ID:fNuZm9nkデバッグ・・・そんなつもりはなかったんですけど、
結果的にそういうことになってましたか・・・。
すみません。
「配列の中から必要なものだけ」という点についても
何かアドバイスが欲しかったので、しつこく聞いてしまいました。
すみませんでした。
>>831
その通りでした。
>>822にて指摘していただいた通り
spliceするのではなく要素を空にする方法にします。
>>832>>834
>View側で表示しないよう分岐
にしても、結局同じように@data内を1行ずつ展開して
表示させるかどうかのチェックをする方法しか思いつきませんでした。
アドバイスありがとうございました。
>>833
もしかしたら、自分のやりたいことと書いてるコードが全然見当違いのことをやっていて
「そんな無駄な処理しなくても、こうやった方が良い」というのがあるのかな、と思って質問しました。
特段、妙なコードを書いているわけではないと分かっただけでもありがたいです。
同じような質問、くだらないことを何度もしつこく書き込みをしてすみませんでした。
今まで懇切丁寧に色々と教えて下さった方々本当にありがとうございました。
0840nobodyさん
2006/06/22(木) 14:53:39ID:???my @checked = qw(1 0 1);# 「年齢」「性別」「電話番号」を出すか
#ループ内で消す
my $i = 0;
foreach my $flg (@checked){
undef $tmp[$i] if $flg;
}
こうするとか。
まぁViewでやるけど。
0841nobodyさん
2006/06/22(木) 15:24:19ID:???じゃあ最後に土産
my %in = (denwa => 1, seibetsu => 0, nenrei => 0, juusyo => 1, hoge => 'hogehoge'); # クエリのデータ?
$in{namae} = 1; # 名前は必ず必要
my @checks = qw(namae seibetu nenrei denwa juusyo); # 含まれるデータの名前
# データ取得
my @data = qw();
open ( LOG, "< name.txt" ) || die ( "ERROR: $!" );
flock ( LOG,1 );
while ( <LOG> ) {
my $d = {};
@{$d}{ @checks } = split (/<>/);
foreach my $key (@checks) {
delete $d->{$key} if (!$in{$key});
}
push (@data, $d);
}
close ( LOG );
# ソート
my $i = 0;
my %jusho = ();
foreach my $name ('北海', '東京', '愛知' , '大阪', '京', '福岡') {
$jusho{$name} = $i++;
}
@data = map {$_->[0]}
sort {$jusho{$a->[1]} <=> $jusho{$b->[1]}}
map { $_->{juusyo} =~ /^(.*?)(?:県|都|府|道)/; [$_, $1] } @data;
foreach my $d (@data) { while (my ($k, $v) = each %$d) { print $k, ': ', $v, ', '; } print "\n"; }
0842nobodyさん
2006/06/22(木) 15:27:23ID:???0843nobodyさん
2006/06/22(木) 15:30:29ID:???0844nobodyさん
2006/06/22(木) 17:30:21ID:???$i = 1;
print $hoge{aaa$i}; だとエラーになるのですが、正しい記述方法は何でしょうか?
0845nobodyさん
2006/06/22(木) 17:36:13ID:???0846nobodyさん
2006/06/22(木) 17:38:57ID:???0847nobodyさん
2006/06/22(木) 17:50:11ID:fJKTYP9wどうすれば良いのでしょうか?現在は↓のように書いています。
print "ほげ".&hoge('abcd')."ほげ";
しかし、なんか綺麗じゃないので、↓のような感じで書く方法とか
あったら、良いなぁと思ってます。
print "ほげ&hoge('abcd')ほげ";
↓のような書き方も良いのですが…。
print sprintf("ほげ%sほげ",&hoge('abcd'));
まだPerlを始めたばかりなので、皆さんの知恵をかしてください。
0849nobodyさん
2006/06/22(木) 17:54:49ID:???"ほげ",
&hoge('abcd'),
"ほげ"
;
#改行しちゃえば?
0850nobodyさん
2006/06/22(木) 17:57:17ID:???printの中に埋め込まない方が良い
個人的には、
print "ほげ", &hoge('abcd'), "ほげ"; # 連結コスト無し
print "ほげ" . &hoge('abcd') . "ほげ"; # だと2回分、文字列連結コストがかかる
print "ほげ&hoge('abcd')ほげ"; # 動作せず
printf("ほげ%sほげ", &hoge('abcd')); # printf, sprintf のコストは重い
0851nobodyさん
2006/06/22(木) 18:02:27ID:???見栄えはあまりねぇ。
逐次出力したくないときは、どっちにしろ文字列連結コストがかかるし。
0853847
2006/06/22(木) 18:05:43ID:???対するコストなんて考えてませんでした。
皆さんの意見が" ,"で繋げる事で一致しているみたいなので、
これからは、" ,"で繋げる方法でいこうと思います。
0854nobodyさん
2006/06/22(木) 18:10:46ID:???0855nobodyさん
2006/06/22(木) 19:14:15ID:???0856nobodyさん
2006/06/23(金) 00:51:44ID:???The script did not produce proper HTTP headers.
Please see the error log to see the detail of the errors.
Depending on the server configuration, you can also run thisscript under CGIWrap debugging.
Usually, either rename or linkthe script temporarily to a file which ends with.
cgidextension, or add a AddHandler cgi-script-debug .cgiline to your .htaccess file.
─────────────────────────────────────
Perlで組んだCGIを実行するとこの様なエラーが出てしまい、困っています
CGIのログファイルに、既にデータが入っていれば、↑のエラーは出ないのですが、
ログファイルの中身が空っぽの場合↑のエラーが出ます。
なぜでしょうか?ログファイルを処理するコードに問題があるのでしょうか・・・・・・?
0857856
2006/06/23(金) 00:52:17ID:???─────────────────────────────────────
sub data {
open(LOG,"< $logname") || &error("ログファイルが開けませんでした");
@logs=<LOG>;
close(LOG);
foreach $line(@logs) {
chop($line);
($atai1,$atai2,$atai3,$atai4,$atai5,$time,$value,$name,$titles,) = split(/\,/,$line);
if (!$line){last;}
print "<TABLE border=\"1\" align=\"center\" width=\"500\">\n";
print "<TR><TD>名前</TD><TD>$name</TD></TR>\n";
print "<TR><TD>タイトル</TD><TD>$titles</TD></TR>\n";
print "<TR><TD>投票</TD><TD>$atai1/$atai2/$atai3/$atai4/$atai5/</TD></TR>\n";
print "<TR><TD>書き込んだ時間</TD><TD>$time</TD></TR>\n";
print "<TR><TD>本文</TD><TD>$value</TD></TR>\n";
print "</TABLE><br>\n\n";
}
}
0858nobodyさん
2006/06/23(金) 01:09:56ID:???見慣れないエラーだな…XREAの鯖か?
それを見る限り、ログファイルが空というだけじゃ特に問題を起こしそうなコードじゃない。
が、それが出るのってもしかしてログファイルが存在しない場合、じゃない?
そうだとしたらerrorサブルーチンのほうをチェック。
特にHTTPヘッダをちゃんと出しているかどうかを確認汁。
どうでも良いが変数名はもうちょっと考えたほうが良いぞ…
valueって日本語で値なんだが…本文は大抵bodyとかtextとかかと。あとなぜにtitleが複数形なのよ。
0859nobodyさん
2006/06/23(金) 01:42:46ID:???0860856
2006/06/23(金) 01:57:18ID:???それがどうも、>>858さんがおっしゃっられた通り「&error;」に問題があるっぽいです・・・・。
ためしに、>>857(&data;)のログファイルの変数を適当な文字列に変え、実行したところ、
「ログファイルが開けませんでした」が無限と出てきました。
しかし、↓はその「error」のサブルーチンですが、取り分け私の目には可笑しいようには見えないのですが・・・・
─────────────────────────────────────
sub error {
local($msg) = @_;
print "<br>\n";
print "<table border=\"0\" cellpadding=\"3\" width=\"500\" cellspacing=\"0\" align=\"center\">\n";
print "<tr><td width=\"100%\" bgcolor=\"#C0C0C0\" align=\"center\">\n";
print "$msg\n";
print "</td></tr>\n";
print "</table>\n";
&data;
&foot;
exit;
}
─────────────────────────────────────
sub foot {
print "</BODY>\n";
print "</HTML>\n";
exit;
}
─────────────────────────────────────
0861nobodyさん
2006/06/23(金) 02:32:49ID:???0862nobodyさん
2006/06/23(金) 07:34:25ID:???0863nobodyさん
2006/06/23(金) 14:40:13ID:???そこが分からん
自分では分からないものなのか?
0865nobodyさん
2006/06/23(金) 16:01:22ID:???0866nobodyさん
2006/06/23(金) 16:58:29ID:QUOZQBvkしょーもないところでハマってしまったので、教えてください。
pack("C",8) → 0x08
pack("C",9) → 0x09
pack("C",10) → 0x0D 0x0A
pack("C",11) → 0x0B
どうも10をバイナリ変換したときだけ0x0Dがついてしまうんですが、
これってなんでですか?
0867nobodyさん
2006/06/23(金) 17:07:46ID:???http://www.din.or.jp/~ohzaki/perl.htm#CRLF_Unify
0868nobodyさん
2006/06/23(金) 17:08:13ID:???大雑把に書けば \r\n
0869nobodyさん
2006/06/23(金) 17:18:27ID:QUOZQBvk$bin='';
for(1..100){
$bin.=pack("C",$_)
}
open(OUT, "> test.bin");
print(OUT $bin);
close(OUT);
exit 0;
↑のコードに意味はないですが、こんな感じで「pack()の第2引数に何か数値が入る」という場合に、
10が入ってきても正しく動くようにするにはどうすればよいのでしょう?
0870nobodyさん
2006/06/23(金) 17:20:41ID:???0871nobodyさん
2006/06/23(金) 17:22:53ID:QUOZQBvk助かりました。ほんとにありがとう。
0872nobodyさん
2006/06/23(金) 22:21:11ID:HrkNw3LRprint "content-type:image/gif;\n\n";
というヘッダを吐き出して試しに画像を返すCGIを作ってみようと思いました。
最終的には画像をいじるCGIを作ろうと思ってるのですが。
バイナリをコピーしてテキストファイルに貼り付けても何故か
89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
という形で張り付きません。何か方法がありますでしょうか?
0873nobodyさん
NGNG0874872
2006/06/23(金) 22:58:10ID:HrkNw3LRなるほど。
それではどうすればいいのでしょうか?
手書きで移すしかないのでしょうか。
0875nobodyさん
2006/06/23(金) 23:16:19ID:???ソースにバイナリを埋め込もうとするなよ、と。
0876nobodyさん
2006/06/24(土) 00:26:02ID:???「 $hoge /= $fuga; 」
で、$hugaの値は始め「0」なのですが、この場合どうすればよろしいでしょうか?
割る数が0だとエラーですよね・・・・
0877nobodyさん
2006/06/24(土) 00:32:56ID:???0878nobodyさん
2006/06/24(土) 00:34:07ID:???経験からすると、そういう時はだいたい計算方法自体が間違ってる。ループの開始値は実は1とか。
まあこれで正しい計算ができると言うのなら $hoge /= $fuga || 1 とか。
0879876
2006/06/24(土) 01:54:46ID:???ありがとうございます。
一応いろいろいじっていて、「$hogehoge = eval { $hoge / $fuga; };
と、形が崩れてしまったのですがこれで動きました・・・が、これでも問題ないでしょうか?
0883nobodyさん
2006/06/24(土) 02:17:12ID:???0で割ったら0にならないものを、無理やり0にしようとしてるんだから
素直に場合わけした方がいいよ。
if ($fuga == 0) {
$hogehoge = 0;
} else {
$hogehoge = $hoge / $fuga;
}
eval使うと遅いし。
$ perl
use Benchmark;
timethese(1_000_000,
{'ore'=>sub{if ($fuga == 0) {$hogehoge = 0;} else {$hogehoge = $hoge / $fuga;}},
'omae'=>sub{$hogehoge = eval { $hoge / $fuga };}});
Benchmark: timing 1000000 iterations of omae, ore...
omae: 6 wallclock secs ( 6.64 usr + 0.00 sys = 6.64 CPU) @ 150625.09/s (n=1000000)
ore: 0 wallclock secs ( 0.39 usr + 0.00 sys = 0.39 CPU) @ 2557544.76/s (n=1000000)
(warning: too few iterations for a reliable count)
0885nobodyさん
2006/06/24(土) 02:48:48ID:LjIFBTanその場合ためらいも無く「flock(LOG,2);」とかやっても問題無いですか?
0886nobodyさん
2006/06/24(土) 04:03:57ID:???flockが使えないような鯖で動かす予定がないなら良いんじゃない?
漏れは、もう長いことflockのためにeval使ったことなんて無いな…
# っつか、flock非対応の環境に出会ったことが無いんで、
# 対応してない環境では致命的なエラーになる事をすっかり忘れてた。
0887872
2006/06/24(土) 17:30:41ID:1EkY/rQfそれじゃあ画像をいじるCGIを作るのが難しいですよ。
どこの何番が何に当たるとか、逐一みたいですし。
あ、勘違いしてるかもしれません。
ASCIIコードで埋め込みたいんです。
バイナリで埋め込むという表現は間違いでした。すみません。
0888nobodyさん
NGNGとか、packとか
0889872
2006/06/24(土) 17:52:23ID:1EkY/rQf89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
こういう感じです。
件のものですが、locationと同じですよね。
まあ
print "location:/img/logo.gif;\n\n";
でやってもエラーが出てしまって困ってるのですが。。。。
なんかスランプです。あつくtえ
0892nobodyさん
2006/06/24(土) 19:40:28ID:???英語で記載したセルとハイパーリンクだけは抽出してくれるのですが、日本語部分が文字化けしてしまいます。
モジュール部分には、以下のように記載しています。
use Spreadsheet::ParseExcel;
use Spreadsheet::ParseExcel::FmtJapan;
use Unicode::String;
Googleなどの検索では、これで上手く言っている人が大部分でした。お判りになる方がいたら、教えてください。
0893872
2006/06/24(土) 21:10:03ID:1EkY/rQfprint "Content-type: image/gif\n\n";
open FH,"../img/logo.gif";
my @img = <FH>;
pack "h", @img;
print @img;
close;
そうしたら正常でない画像が表示されました。多分変換部分が間違いなんですね。
hじゃなかったのかな。
>>890
すみません。暑さに参っておりました。35度って凄いですね。
冷房使えない体なので。
フォトショップみたいなCGIを作ろうと思ってます。
ご覧の通り未熟ですので今年一杯の趣味感覚で取り組んでいます。
>>891
ありがとうございましたm(__)m
やさしさを感じましたm(__)m
0894872
2006/06/24(土) 21:12:18ID:1EkY/rQf文字コード問題では?
モジュールに渡す時に決められた文字コードにしておかないといけないとかはないのですか?
その他もジーコ度全般を見直してみhてあ。
0897nobodyさん
2006/06/25(日) 00:04:20ID:???掲示板ログから出力すると、行数が多いので、
件名だけか、本文の何行まで抜き出すという風に出来たらと思うんですけど。
@match = map { $_->[0] }
sort { $b->[18] <=> $a->[18] }
map { [$_, split /\|\|\|/] }
@match;
my$i = 5;
foreach $line (@match) {
@mdata = split(/\|\|\|/,$line);
if ($i > 0) {
print "<CENTER>\n";
&table_html($HoD);
&subj_date_name_hp_html ("main", \@mdata, $HoD);
0898nobodyさん
2006/06/25(日) 00:14:20ID:???0899872
2006/06/25(日) 00:28:43ID:CLTK8aRMbinmodeで、rawにやってみます。ありがとうございます。
>>897
決めたバイトだけ読み取るとか・・・・というかどういう形式で保存されてるのかさえ
わかりやすく説明したらきっと詳しい人がズバリで教えてくれると思いますよ。
0900nobodyさん
2006/06/25(日) 01:37:46ID:???spliceで削除しちゃえばいいんじゃないのか?
0901897
2006/06/25(日) 03:45:53ID:???ありがとうございます。
バイトで読み取りをしてみたのですが、うまくいかず…。
もっと勉強します…。
spliceでいけました。
>>900
spliceでいけました。
ヒントありがとうございます。
本当に本当に助かりました!
ありがとうございました。
0902nobodyさん
2006/06/25(日) 06:35:30ID:???img/logo.gifが純正のgifファイルなら、
何も変換せずにprint <FH>で表示できる。
windows環境ならbinmodeが必要。
binaryが見たいなら、とりあえず
print unpack"H*",join"",<FH>で見れる
各要素を配列として得たいなら
my@a=unpack"C*",join"",<FH>など、・・・
0903nobodyさん
2006/06/25(日) 07:42:22ID:???0904nobodyさん
2006/06/25(日) 10:22:03ID:???フォトショップの何をしたいのかさっぱりわからんw 全体だったらかなり無謀だよね。
0905nobodyさん
2006/06/25(日) 12:03:42ID:???Photoshop を Web アプリとして再実装できたら面白いと思ふ。
例えば中小規模でのグラフィックワークステーション共有とか、コスト面でのメリットが出るならいけそうじゃないか?
0906nobodyさん
2006/06/25(日) 12:06:28ID:???0907872
2006/06/25(日) 12:47:39ID:CLTK8aRMopen FH,"../img/logo.gif";
binmode FH;
my @img = <FH>;
pack "raw", @img;
print @img;
close;
これだと画像部分が×になって表示されません。でも画像のサイズはあってます。
print "Content-type: image/gif\n\n";
open FH,"../img/logo.gif";
binmode FH;
print <FH>;
close;
だとやっぱりぐにゃぐにゃの画像になって表示されてしまいます。
winXP
apache1.3.3
active perl 6.8
です。
0908nobodyさん
2006/06/25(日) 13:10:04ID:???もお忘れなく
0909872
2006/06/25(日) 13:22:05ID:CLTK8aRMprint "Content-type: image/gif\n\n";
open FH,"../img/logo.gif";
binmode STDOUT;
print <FH>;
close;
ありがとうございました。これでできました。
binmode FH;はファイルをバイナリレベルでいじる時で、出力をバイナリにするには
binmode STDOUT;が必須だったのですね。
ありがとうございました。
>>904-905
専用サーバを借りてるので、時間掛けながらゆっくりやろうとかと思います。
どこらへんまで出来るのかは現時点の私ではわかりませんので、みなさんからすると
アホなことかもしれません。でも面白そうなので。
0910nobodyさん
2006/06/25(日) 13:44:45ID:???index,127.0.0.1,20060624210600,Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
index,127.0.0.1,20060624210600,Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
こういうアクセスログファイルがあって、
open FD,"access.log";
while (<FD>){
print $_,"<br>\n";
}
とするとブラウザのところで何行にもなってしまいます。
つまりwhileが行末の改行以外でちょんぎってはじめてしまってるのです。
一応
open FD,"access.log";
my @line = <FD>;
close FD;
print $line[0];
も試してちゃんと行ごとの配列になってましたので、whileの影響だとは思うのですが。
0911nobodyさん
2006/06/25(日) 13:46:56ID:???index,127.0.0.1,20060624210600,Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
index,127.0.0.1,20060624210600,Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
こういうアクセスログファイルがあって、
open FD,"access.log";
while (<FD>){
print $_,"<br>\n";
}
とするとブラウザのところで何行にもなってしまいます。
つまりwhileが行末の改行以外でちょんぎってはじめてしまってるのです。
一応
open FD,"access.log";
my @line = <FD>;
close FD;
print $line[0];
も試してちゃんと行ごとの配列になってましたので、whileの影響だとは思うのですが。
多分<FD>これでちゃんと行ごとに渡そうとしてるにもかかわらずその中の何かのコードに
whileが反応して行の途中で区切って処理を開始してしまうんだと思います。
whileに行ごとにやらせたいのですが、何かwhileのモードを変える方法でもあるのでしょうか?
0912nobodyさん
2006/06/25(日) 14:09:12ID:???なんとか使うことは出来ないのでしょうか?
0914nobodyさん
2006/06/25(日) 16:38:32ID:???何言ってんの?
while (<FD>){
print $_;
}
こうすれば行ごとになるんでしょ? それに加えて \n 入れたら2行になるの当たり前じゃん。
0915915
2006/06/25(日) 16:58:59ID:???if($old_rand == $rand)
{ $rand = $rand + 1; }
if($rand == 0)
{ $key = "000"; $old_rand = $rand;}
elsif($rand == 1)
{ $key = "001"; $old_rand = $rand; }
elsif($rand == 2)
{ $key = "002"; $old_rand = $rand; }
elsif($rand == 3)
{$key = "003"; $old_rand = $rand; }
elsif($rand == 4)
{ $key = "004"; $old_rand = $rand; }
else
{ $key = "006"; $old_rand = $rand; }
上記の部分を処理が来るごとに使っています。
前回と同じ値の場合は+1して2度連続で同じkeyにならないようにしているのですが
何故か同じkey(例:$key = 002等が)が重なることがあります。
前回と同じ数値の場合は+1しているので重なることはないと思うのですが
なぜ同じ数値が出るのでしょうか?
どこか間違っている場所があればアドバイスいただければと思います。
0916nobodyさん
NGNG+=とsprintf使った方がよさげ
0917nobodyさん
2006/06/25(日) 17:13:02ID:???$rand += 1 if ($old_rand == $rand);
if ($rand < 5) {
$key = sprintf("%03d", $rand);
} else {
$key = "006";
}
$old_rand = $rand;
006は重なるだろうけど、他の部分で$old_rand変更しちゃってるとか。
0918915
2006/06/25(日) 17:21:20ID:???もしかして
{}内で$old_randに入れても{}内だけで有効で
{}外では$old_randって何も入ってない状態になりますか?
もしそうなら私のバカなミスということになりますが・・・。
0919nobodyさん
2006/06/25(日) 17:23:14ID:???同じ処理が全部の条件に入っていたから括り出しただけ
0921nobodyさん
2006/06/25(日) 18:51:53ID:???こんなコード書いてみた。いろいろ弄って考えてみて。
foreach(1..1000){
r();
}
exit;
BEGIN{
my ($old_rand, $old_key) = (0, 0);
sub r
{
my $rand = int(rand(6));
$rand++ if($old_rand == $rand);
my $key = sprintf("%03d", ($rand < 5 ? $rand : 6));
print "OUT! key:$old_key,$key rand:$old_rand,$rand\n" if ($old_key eq $key);
$old_rand = $rand;
$old_key = $key;
return $key;
}
}
# 本当は、元のままのコードを使いたかったのだけれど、
# プログラム関連の板で改行制限が厳しいとはどういうこった!>ひろゆき
0922nobodyさん
2006/06/25(日) 19:09:56ID:???0925911
2006/06/25(日) 21:28:57ID:???my %access;
# どのページにアクセスしてきたか
$access{p} = ( p => "index" );
# アクセス人物のIPアドレス
$access{ip} = $ENV{'REMOTE_ADDR'};
# アクセス時刻の記録
$access{time} = sprintf "%04s%02s%02s%02s%02s%02s",sub{shift()+1900,shift()+1,@_}->(@{[gmtime(time+32400)]}[5,4,3,2,1,0]);
# アクセス人物のブラウザ
$access{browser} = $ENV{'HTTP_USER_AGENT'};
# 書込み処理
open FH,"+>access.log";
flock FH,2;
my @line = <FH>;
my @new_line = join ",",@access{qw/p ip time browser/};
for ( my $i=0; $i<@line; $i++ ){
my @temp = split /,/,@line;
if ( $access{ip} ne $temp[1] and 1000000000 > $access{time} - $temp[2] ){
push (@new_line,join (",",@temp));
}
}
for ( my $i=0; $i<@new_line; $i++ ){ print $new_line[$i],"\n" }
while ( <@new_line> ){ print FH $_,"\n" }
close FH;
これを実行するとブラウザには一行で表示されますが、ファイルにはブラウザの種類部分が
何行にもわたって書き込まれてます。
ファイルに書込みするのもforでやれば問題は解消します。
なぜでしょうか?
0926nobodyさん
2006/06/25(日) 21:52:14ID:???配列を<>に入れてるのも初めて見たわ。
0927nobodyさん
2006/06/25(日) 22:03:36ID:???+>で開いて読み込めるわけないし。+<の間違いだとしてもtruncateしてないし。
split /,/,@lineって$i使ってないし。
で、
> ファイルにはブラウザの種類部分が何行にもわたって書き込まれてます。
というのは、
index,127.0.0.1,20060624210600,Mozilla/4.0 (compatible; MSIE 6.0;
Windows NT 5.1; SV1;
.NET CLR 1.1.4322)
こんな感じになるって意味?
そうなるとせっかくの乱数が偏って、ますます乱数から遠のくかと♪
0929911
2006/06/25(日) 22:28:53ID:???え?実際にそのソースで動作させた結果をお話してるのですが?
+>で読み込めますよ?
http://www.rfs.jp/sb/perl/02/08.html
それとtruncateがこの場面で必要ですか?
ヤケに煽りっぽい口調ですし・・・・単なる荒らしですか?
ちなみにアクセスログファイルには以下のように書き込まれます。
index,127.0.0.1,20060625212623,Mozilla/4.0
(compatible;
MSIE
6.0;
Windows
NT
5.1;
SV1;
.NET
CLR
1.1.4322)
ただwhileでブラウザに出力すると上記のようにはならないのでwhileだけの問題ではなさそうですが。
0930nobodyさん
2006/06/25(日) 22:30:25ID:???(1)欲しい乱数の範囲を連番で配列へ格納
(2)その配列をシャッフル
これでOKよ
0931911
2006/06/25(日) 22:31:28ID:???>split /,/,@lineって$i使ってないし。
あ、ありがとうございます。
・・・やっぱり普通に親切な人なのかな?
0932911
2006/06/25(日) 22:36:58ID:???>split /,/,@lineって$i使ってないし。
なんでこれで動いてるんでしょうか。
ちゃんと書き込まれる内容があってるというのは不思議です。
ローカルレベルなのでipが一つだけなのでたまたま動いてるんだと思いますが。
my @temp = split /,/,@line;
これの結果って@lineをスカラで評価するわけですから、本来@tempには
数字しか入らないとおもうのですが。
なぜまともに中身が入ってるのですかね・・・
0933nobodyさん
2006/06/25(日) 22:43:11ID:???ここが原因。
<> でくくると空白ごとに改行に置換される模様。
つかですね、配列に入ってるなら
print FH @new_line;
でえぇですやん
0934911
2006/06/25(日) 22:52:08ID:???空白ごとですか。
でもそれだとどうしてブラウザに出力したときは違う結果になるのでしょうか。
よければ>>925のソースにHTTPヘッダをプラスして実行してみてください。
whileでブラウザに出力してソースをみてもブラウザの種類のところに改行は
自動挿入されてないのです。
ファイルに書き込む時だけそうなってるんですよね。
確かに
$`="\n";
print FH "@new_line";
でよかったですね。
0935911
2006/06/25(日) 22:54:37ID:???print "content-type:text/html;charset=euc-jp\n\n";
my %access;
# どのページにアクセスしてきたか
$access{p} = ( p => "index" );
# アクセス人物のIPアドレス
$access{ip} = $ENV{'REMOTE_ADDR'};
# アクセス時刻の記録
$access{time} = sprintf "%04s%02s%02s%02s%02s%02s",sub{shift()+1900,shift()+1,@_}->(@{[gmtime(time+32400)]}[5,4,3,2,1,0]);
# アクセス人物のブラウザ
$access{browser} = $ENV{'HTTP_USER_AGENT'};
# 書込み処理
open FH,"+>access.log";
flock FH,2;
my @line = <FH>;
my @new_line = join ",",@access{qw/p ip time browser/};
for ( my $i=0; $i<@line; $i++ ){
my @temp = split /,/,@line;
if ( $access{ip} ne $temp[1] and 1000000000 > $access{time} - $temp[2] ){
push (@new_line,join (",",@temp));
}
}
while ( <@new_line> ){ print $_,"\n" }
while ( <@new_line> ){ print FH $_,"\n" }
close FH;
ブラウザでは普通に出力され、ファイルには変な改行が加えられて書き込まれます。
0936927
2006/06/25(日) 22:56:13ID:???そこのサイトかー勘違いしやすい書き方なんだよな…これ。
http://pc8.2ch.net/test/read.cgi/tech/1149259409/n272-273
Perlの関数リファレンス参照
ttp://perldoc.jp/docs/perl/5.6.1/perlfunc.pod
| '+>' は最初にファイルを上書きします。
これだけじゃわかりにくいんで、もう一つ。+>のモードと言うのはfopenのw+に相当するんだが
ttp://www.linux.or.jp/JM/html/LDP_man-pages/man3/fopen.3.html
| w+ 読み取りおよび書き込みのために開く。ファイルが存在していない場合には新たに作成する。
| 存在している場合には長さゼロに切り詰められる。ストリームはファイルの先頭に位置される。
とあるように、読み込みは出来るけれど、開いたときに中身が空になる。
つまり、
my @line = <FH>;
は@lineに何も入ってきてないはず。
# 口調は雑だけど煽りのつもりは無いのでキニスンナ
# うっかり素を出すと敬語もどきになってしまうんですよ
0937911
2006/06/25(日) 23:17:15ID:???なるほど!
ローカルチェックだったので初め消されても支障がなかったようです。
自分のipは一つで>>935をなんどやってもどちらにせよ中身を読み込む必要がなかったので。
splitとopenで間違いがあるのを教えてくれてありがとうございました。
すみませんあらぬ疑いを向けてしまって。質問者の分際でごめんなさいm(__)m
それでですが、本来の目的である「期待の動作をするスクリプトの作成」
からはちょっと脱線してしまってまして、なぜ>>935のソースでブラウザ出力内容と
ファイル書込み内容に差がでるのかが気になってしょうがないのですが。
>>936さんはわかりますでしょうか。
ファイルの書込みとwhileと。複雑に絡んだ現象なのでしょうか。
ちなみにperlのバージョンは5.8.1のwinxPです。
0938927
2006/06/25(日) 23:33:09ID:???ブラウザではHTMLとして解釈されていると言うことを忘れているのではないか。
HTMLソースを見るか、
while ( <@new_line> ){ print $_,"<br>\n" }
while ( <@new_line> ){ print FH $_,"\n" }
とすれば同じように表示されると思う。
レス数が900を超えています。1000を超えると表示できなくなるよ。