トップページ⇒php
1001コメント328KB

【Perl】初心者コーナーPart10

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。02/02/24 22:18ID:zOj6Yq/3
いらっしゃーい、Perlのコーディングで困ってる人のスレです。

1:自分はこう言う事がしたい。
2:それでこんな風にやってみたが・・・
3:それだとこんなエラーが出て上手く行かなかった。

1と3が無いと誰も答えられないよ、良い回答は良い質問から。
一緒に勉強しましょう。

参考書籍はこちら【【Perl,CGI】参考書籍 第2版 】
http://pc.2ch.net/test/read.cgi/php/988809842/
CGIの質問はこちら【CGIだけど、なんか質問ある?part5】
http://pc.2ch.net/test/read.cgi/php/1009331505/
その他の雑多な話題は、【CGIに依存しないPerlの話題一般】
http://pc.2ch.net/test/read.cgi/php/991313362/

過去ログ、その他の役立ち情報は>>2-10を見よう。
0353nobodyさん02/03/10 12:48ID:???
>>351
$i = %hash;

で、つじつまは合うなぁ。

汚いけど

print(%hash + 0);

とかは。
0354テストテスト02/03/10 12:49ID:FplTavEM
>>349
板違い。そんなものビギナーが気にする必要なし。
どこかのアアホサイト見てるんだけうが
HTTP 1.1でセッションを100個張るレジスト書き換え.regファイルとか
配布してるが、意味がないしスーパー迷惑なのでやめれ。
035534702/03/10 12:51ID:???
ぐぐるったら、すぐ出てきちゃった。
$num = keys %HASH;
でいいみたい。(keys のかわりに valuesでもいいんだって)
http://plaza27.mbn.or.jp/~satomii/jdoc/perltut/associative.html
0356ドビ02/03/10 12:52ID:???
なるほど。「忘れろ」ってことだな?
あと、板違いってことも気付いた。
ごめんな。
0357nobodyさん02/03/10 12:59ID:???
>>355
あ、そうか。キー一覧リストの大きさ数えればいいんだ。
コロンブスの卵ちっく。
035835102/03/10 13:02ID:???
>>353
%hash = (A=>1,B=>2,C=>3);
$i = %hash;
print($i,"\n");
print(%hash+0);
だと
3/8
3
になりました。
OS依存かと思って調べてみたら
http://www.kt.rim.or.jp/~kbk/perl5.005/perldata.html
>返される値は使 用しているエントリの数と、割り付けられているエントリの数を、スラ ッシュで区切った文字列です
らしいです。
お騒がせしました。
0359nobodyさん02/03/10 13:10ID:???
>>358
%h = (1,2,3,4,5,6,7,8,9,10);
print scalar keys %h,"\n";
print scalar %h,"\n";
が
5
4/8
って返ってくるんだよね。エントリ=要素ではないのかな。
036035902/03/10 13:14ID:???
>>358のリンク先にちゃんと書いてありました。逝ってきます。
036134602/03/10 13:19ID:???
>>355
ああ!大感謝です!
本当にありがとうございます。おかげさまでとても無駄な作業部分を消すことが出来ました。
0362nobodyさん02/03/10 15:12ID:GU0dbd6s
PerlでCGI作ってるんですが、実行している自分自身のファイル名を
調べることってできるんでしょうか。例えば、bbs.cgiっていうCGIの中で、
bbs.cgiっていう文字列を自動的に得たいのです。同じコードをあっちこっちで
使っていて、更新するときに中身の書き換えを不要にするためです。
036334102/03/10 15:12ID:Ew4WhUAi
みなさんありがとうございます。

そか、、NTTが許可したサーバーでだけ使えるんですね^^;
アドバイスありがとうございました。
0364nobodyさん02/03/10 15:16ID:???
>>362
$0
0365nobodyさん02/03/10 15:21ID:GU0dbd6s
>>364
お、それはヒントですか?調べてみます。ありがとうございます!
0366nobodyさん02/03/10 15:23ID:???
>>365
すまんがワラタ・・・
036736502/03/10 15:28ID:???
>>366
なんでだ??うそっぱちか?

>>$0 #perlスクリプトのコマンド名
コマンド名ってのがcgiファイル名ってことですね??言葉が難しいや。
036836602/03/10 15:30ID:???
>>367
ごめんごめん。
>>364はずばり回答そのものだったので、>>365の「ヒントですか?」が
ちょっと面白かったのよ。
036936502/03/10 15:34ID:???
ははは。失礼!調べたら本当にそのまんまでした!
できたー!!すげー、一見汎用性あるっぽくてカコイイ!!
0370nobodyさん02/03/10 15:35ID:???
panic: utf8_length: unaligned end
なんかエラーがでて文字列の長さが取得できないんですが…。

037137002/03/10 15:40ID:???
同じ文字列を使った単純なテストだと問題ないし。
何故…。
037237002/03/10 15:44ID:???
と思ったらuse utf8すると再現するっぽい。
#!perl
use utf8;
length '時';
__END__

しかし問題なのは実際のコードでは use utf8 などしていないということ(鬱
037336502/03/10 15:56ID:GU0dbd6s
CGIファイルの場所を調べることはできますか?
なんていうんだろう、urlっていうのかパスっていうのか、よくわからないんですけど
http〜〜〜cgi-bin/bbs/bbs.cgi
みたいな感じのものを調べたいのです。
0374nobodyさん02/03/10 16:00ID:???
use utf8ってスクリプトの文字コードがutf8ってことだけど・・・
utf8で保存してる?

>しかし問題なのは実際のコードでは use utf8 などしていないということ(鬱
何か他にモジュール使ってない?
0375nobodyさん02/03/10 16:06ID:???
>373
print 'http://' . $ENV{'HTTP_HOST'} . $ENV{'SCRIPT_NAME'};
で出るかな?
037637002/03/10 16:08ID:???
スクリプトの文字コードはEUC-JPです。

どうやらDBI+DBD::SQLiteでDBからフェッチした文字列がおかしい模様…。
でもJcode::getcode()で調べてもEUC-JPなので謎です。
0377nobodyさん02/03/10 16:09ID:???
>>373
CGI.pmの重さが気にならなければurlメソッド/関数で取得可能。
0378nobodyさん02/03/10 16:12ID:???
>>376
use utf8;を加えて、文字コードをutf8で保存してから実行するとどうなる?
0379nobodyさん02/03/10 16:26ID:???
>>370
Perlのバグじゃない?新しいのに入れ替えてみれば?
0380nobodyさん02/03/10 16:26ID:???
>>378
そうするとpanicは避けられるっぽいです。
ただそうすると大幅に書き換えなければいけないので出来れば避けたいです…。

# とりあえず完全に再現できるスクリプトを書き中…
038136502/03/10 16:28ID:GU0dbd6s
下痢下痢で遅れました..(鬱)。

>>375、>>378
ありがとうございます!$0みたいにずばりはないんですね。
ちょっと調べてみます。
038237002/03/10 16:48ID:???
再現できました。
これで
"panic: utf8_length: unaligned end at test.pl line 20."です
#perl -w

use DBI;
unlink 'test.db';
my $dbh = DBI->connect('dbi:SQLite:test.db');

$dbh->do(<<_SQL_);
CREATE TABLE test( foo CHAR(100) );
INSERT INTO test VALUES('テストだよ');
_SQL_

my $sth = $dbh->prepare(<<_SQL_);
SELECT * FROM test
WHERE foo like '%';
_SQL_
$sth->execute();

$\ = "\n";
while($_ = $sth->fetchrow_arrayref()){
print length($_->[0]);
}
__END__
038336502/03/10 16:54ID:???
>>375さんの方法でできました!ありがとうございます!
0384nobodyさん02/03/10 16:58ID:???
うーん、20行目の$_->[0]がutf8になってないってことでしょ?
use Jcode; して、20行目を
print length (jcode($_->[0])->utf8);
にしてみるとどう?
038537002/03/10 17:07ID:???
ちなみにテストスクリプトの文字コードはEUC-JPです

->utf8()では問題無しですが、->euc()だとpanicです

察するに内部フラグがどうにかなってるっぽいんですが…。
# さっきのスクリプト後半
$\ = "\n";
print join ' ', unpack 'C*', ('テストだよ');
print length 'テストだよ';
while($_ = $sth->fetchrow_arrayref()){
print join ' ', unpack 'C*', ($_->[0]);
print length $_->[0];
}
__END__
出力:
165 198 165 185 165 200 164 192 164 232
10
165 198 165 185 165 200 164 192 164 232
panic: utf8_length: unaligned end at test.pl line 23.
038638402/03/10 17:23ID:???
んー、内部で誰か(多分DBI)がuse utf8してるからlengthへの引数を
utf8なやつだと解釈しようとして失敗してる(eucなんだから当然)からなわけで。
だからlengthに渡すものをutf8に変換しておこう、と言う改造をしてみたんだが。
納得いかないならこんなのとか。
{
no utf8;
$\ ="\n";
while ($_ = ....){
print length($_->[0]);
}
}
038738402/03/10 17:34ID:???
あれ?よく読んでなかった。
なんか勘違いした事書いたかも。スマソ。
038837002/03/10 17:41ID:???
>>386
申し訳ない、>>384が目に入ってませんでした。
それでOKです!

いろいろ試した結果、eval qq{"$_->[0]"}でも正常化できるみたいです。

でもno utf8じゃダメっぽいです…。

とりあえず、解決たので一安心です。
どうもありがとうございました。
0389nobodyさん02/03/11 01:26ID:???
>>346,355
今さらでスマンが、
keysやvaluesでいくと%HASHが巨大だった場合に危険じゃない?
どうせやるなら
++$num while (my ($key, $value) = each %HASH);
とか?めんどくさいけど。
0390nobodyさん02/03/11 01:56ID:???
>389
代入はいらないのじゃない?
0391nobodyさん02/03/11 02:00ID:???
>>389
スカラコンテキストで使うとそれぞれの数を返すっていうkeysやvaluesの機能でしょ.
内部でいちいち展開して数を数えるような,非効率的な事はやっていないと思うよ.

use Benchmark;

my $num = 0;
my %hash;
for (1 .. 1000000) { $hash{$_} = $_ }

timethese 1 => {
'++' => sub { ++$num while (my ($key, $value) = each %hash) },
keys => sub { $num = keys %hash }
};

# 結果
#
# Benchmark: timing 1 iterations of ++, keys...
# ++: 5 wallclock secs ( 4.79 usr + 0.00 sys = 4.79 CPU) @ 0.21/s (n=1)
# keys: 0 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
0392nobodyさん02/03/11 02:46ID:???
◎
$num = keys %hash;
○
++$num while each %hash;
×
++$num foreach keys %hash;
0393nobodyさん02/03/11 13:07ID:ILIPqmP1
処理中に5秒間待たせるような処理に今は
while文で只管ぐるぐる回して
5秒ぐらいで処理を抜けるような感じにしています。
でも、なんかもっとちゃんとした方法があると思うんですがどんな方法があるんでしょうか?。
0394nobodyさん02/03/11 13:20ID:???
>>393
sleep or select
039539302/03/11 14:17ID:???
>394
やはりこういうものがあったんですね(^^
ありがとうございました。
もっと勉強してきます・・・
0396nobodyさん02/03/11 18:53ID:???
http://natto.2ch.net/test/read.cgi/mass/1015750980/

コレを見てくれ!
0397nobodyさん02/03/12 02:51ID:???
perlでtime関数を使用し、SSDを発生させたいのですが、
スクリプトがわからないのでお教えいただけませんでしょうか?
または参考URLをお願いします。
0398nobodyさん02/03/12 02:56ID:???
SSDが何かわからん俺は逝ってよし?
0399sage02/03/12 03:05ID:XpAJ+W0c
SSD…恥ずかしながら僕も初耳。
0400nobodyさん02/03/12 03:13ID:???
>>398
>>399
乱数のことです。
0401nobodyさん02/03/12 03:31ID:???
>397=400
基本はこれだけど, Perl5からは srandで種作らなくても自動で最適な種が作られるようになってる。
srand time;
print rand 100;
0402nobodyさん02/03/12 04:49ID:???
>>400
rand 100
は何を表すのですか?
0403nobodyさん02/03/12 04:52ID:52qV3w5q
ちょっとでかめで、しっかりした実装されてる、
システム公開してるとこ、無いですかね、
しっかりした、ソース見て勉強したいんですけど、
0404nobodyさん02/03/12 04:53ID:52qV3w5q
>>402
0〜100未満のランダムな数がくるぞ
(少数含むから、気をつけれ!)
0405nobodyさん02/03/12 06:34ID:mNSx+HCB
いきなり質問申し訳ありません。

「更新」ボタンの無効化ってどうやるんですか?
0406nobodyさん02/03/12 07:25ID:???
>405
・・・
0407nobodyさん02/03/12 07:37ID:???
>>405
こ、更新ボタンを無効化するの?何のために?お互い困るんじゃない?
0408nobodyさん02/03/12 09:57ID:???
>>405
それができるくらいのハッカーになりたいってことか?
0409nobodyさん02/03/12 10:43ID:???
あれだ、JavaScriptの"戻る"ボタンの無効の延長線じゃないか?
それか、アプローダとかでリロードしないで欲しいとか。
0410nobodyさん02/03/12 11:09ID:???
まぁ、どちらにしてもPerlの仕事じゃないな。
041137002/03/12 11:10ID:???
(>>370-388)
ふと思いついてDevel::Peekでダンプしてみたところ

SV = PV(0x1c4a57c) at 0x1c2f258
REFCNT = 1
FLAGS = (POK,pPOK,UTF8)
PV = 0x1c8aff0 "\245\306\245\271\245\310\244\300\244\350"\0
CUR = 10
LEN = 11

やっぱりUTF8フラグが立っている模様。
これ、バグですよねぇ…。英語書ける方、誰か報告してくれないかな…。
041240502/03/12 13:34ID:eWSq/Ah6
説明不足でした。

submitでhtmlの情報をcgiに送る。
↓
cgiがログファイルをいじる。
↓
cgiが呼び出されて表示されたその画面で「更新」ボタンを押す。
↓
もう一度ログファイルをいじる。
↓
ログファイルが変になる。
↓
(+д+)マズー!

具体例。
ログファイルの配列:@array=(0,1,2,3)
一度目push(@array,4);という命令を出す。→@array=(0,1,2,3,4)→ログファイルに書き込む
リロードするともう一度push(@array,4)を実行する→@array=(0,1,2,3,4,4)
→困る。どなたか対策を教えてください。
0413nobodyさん02/03/12 13:46ID:pCWuH9pI
すみません。
掲示板CGIの改造をしたいのですが、
チェックボックスを付けて、それがオフの場合投稿を弾いてメッセージを表示するにはどうしたらいいのでしょう?
0414nobodyさん02/03/12 13:48ID:???
>>412
前回の内容と比較すれば?
それとcgiに書き込んだあと、htmlファイルにリダイレクトさせるとか。
そうすれば更新ボタン押してもhtmlファイルをGETするだけでしょ。
041540502/03/12 13:50ID:eWSq/Ah6
>>414
ありがとうございます。
でも、すみません、リダイレクトって何ですか?
0416nobodyさん02/03/12 14:10ID:???
>>415
Locationヘッダを出力したり、HTMLのMETAタグで飛ばしたり。
0417nobodyさん02/03/12 14:11ID:???
>>413
> チェックボックスを付けて、それがオフの場合投稿を弾いてメッセージを表示する
INPUT TYPE=checkbox とか、
フォームデータのデコード とか、
検索かけてみて、それでも解らなければそこを聞くのが良いんでない?

と初心者の俺が口を挟んでみるテスト。
0418nobodyさん02/03/12 14:25ID:h6G3oh/x
>>417
アドバイスありがとうございます。
かすってるサイトを発見したので、掲示板に応用するため試行錯誤してみようと思います。
0419nobodyさん02/03/12 14:39ID:???
>>417
初心者のくせに的確だぜ。
このままではわしの地位が・・・。
大きくなる前に潰しておかねばの・・・ふぉっふぉっふぉ。

と、何かを企ててみるテスト。
0420nobodyさん02/03/12 14:51ID:h6G3oh/x
で、今やってみました。

コメント入力欄のあたりに
<INPUT TYPE="checkbox" NAME="a" VALUE="b">書きこみをOKする<BR>

って入れて、名前が入ってないとエラーを返す部分があったのでそこに
if ($a eq "") { &error("オンにしてちょ。",'NOLOCK');

ってやってテストしてみたらオンでもオフでもエラーを返されてしまいました。
別にvalueがbの場合用の処理(?)を書かなくてはいけないのでしょうか?
ちなみに上のは名前が入ってないとエラーを返す部分をちょっと変えただけです。
0421nobodyさん02/03/12 14:52ID:???
>>419
プログラム組むのを仕事にしてる人からしたらメチャメチャだろうけど
自分なりに考えて掲示板組んでみたりしたもので。
やっぱり頭使って悩みながら覚えるのが一番上達早いかなと。。

>>417
あ、もし具体的な改造依頼するなら改造スレッドでよろしく。
スクリプト改造工房 Part4
http://pc.2ch.net/test/read.cgi/php/1012839651/
0422nobodyさん02/03/12 14:57ID:h6G3oh/x
>>421
そっちに行きます。スマソ
0423417=42102/03/12 15:15ID:???
>>422
自力で書こうとしてたしこっちで良かったんじゃないかなぁ。。
余計なこと言ったかも。スマソ。
0424nobodyさん02/03/12 15:16ID:???
>420
とりあえず、$aじゃなくて$FORM{'a'}とかじゃないのか?
0425nobodyさん02/03/12 16:50ID:+eqUJIVR
use Socket;を使ってサーバからhtmlを取得するものを作ったんですが、
HTTPリクエストを送って反応がなかった場合スクリプト自体が止まってしまいます
リクエストを送って30秒間反応がない時には次の処理に行く といった処理をするにはどうすればよいのでしょうか?
0426nobodyさん02/03/12 17:07ID:???
>>425
素人は素直にLWPを使うのが吉。
042742502/03/12 17:19ID:???
こんな便利なものがあったんですね(^^;
ありがとうございます。
0428nobodyさん02/03/12 18:15ID:???
flockの信頼性&利便性はどうなんでしょ?
Perlメモのファイルロックなど自前のファイルロックもありますが,
flockが使える環境ならできるだけflock使ったほうがいいんでしょうか?
0429nobodyさん02/03/12 18:17ID:???
>>403
読んだことないけど,このあたりは大きそう。
http://www.h14m.org/
http://tds.dive-in.to/
0430nobodyさん02/03/12 18:17ID:???
>>428
サーバによる。
ファイルとかシンボリックリンクとかよりよっぽど。
0431nobodyさん02/03/12 18:20ID:???
>428
下手に自前でやるより信頼できると思われ。
WinNT環境だと,flock使ってもロックしないって話を聞いたことがあるような。ないような。
0432nobodyさん02/03/12 19:57ID:???
>>428
漏れも迷わずflock()使う。
プロセスが死ぬとロックが自動的に外れるところがおいしい。

ちなみに、Solarisでは、ライトオープンしないと排他ロックできないという
ことに気づくまで、結構悩んだ。(なんか他のOSだとリードオープンでも排他ロック
できちゃったりした記憶が・・・)
0433ぼくフェロー02/03/12 20:11ID:/5Jn0bAA
お尋ねしたいことがあります.

$a='100' => 数値
$a='-10.0' => 数値
$a='1e+10' => 数値
$a='abc' => 数値ではない.

のような判断をしたいのですが良い方法が分かりません.
すなわち,ある変数 $a に文字列が入っているのですが,
数値を表すことができるか否か判別するよい方法はないでしょうか?


0434nobodyさん02/03/12 20:15ID:???
>433
マルチポストするくらいなら正規表現でも書いてろ。
0435ぼくフェロー02/03/12 20:21ID:/5Jn0bAA
ごめんなさい.
043642802/03/12 20:44ID:???
なるほど。
信頼性も自前<<flockなのか。
なら自前lockのメリットはプラットフォームの問題のみなのか。
素直にflock使うか・・・
0437ぼくメイト02/03/12 20:51ID:???
>>433
あ、こんなところでもお会いしましたね。記念に。
$tmp = $a;
$tmp++;
print "$a is num\n" if $tmp == $a+1;
0438nobodyさん02/03/12 21:02ID:???
>>433
>数値を表すことができる
↑この仕様がわかりませんが、
if ($a =~ /^([+-]?\d*\.?\d*)([eE][+-]\d+)?$/ and $1 !~ /^[.+-]*$/)
みたいな感じかな?
数字が(Perlの変数で表せないほど)たくさん並んでもマッチするけど・・・
0439nobodyさん02/03/12 21:40ID:p/r//4Pi
flockが実装されてるか調べようと,以下のように書いてみたんですが
これで正しく判定できますか?
eval {flock DATA,1 or die $!};
print "flock使えません\n" if $@;
0440nobodyさん02/03/12 22:52ID:???
flockがNFSでダメダメというのは都市伝説か?
http://www.jp.qmail.org/q103/jman5/maildir.html
0441nobodyさん02/03/12 23:18ID:???
> NFSの実装によっては信頼できるロックをまったく持っていません
~~~~~~~~~~~~~~~~


0442nobodyさん02/03/12 23:21ID:p/r//4Pi
>440 検索かけてみたらこんなのがあった。
http://www.adl.nii.ac.jp/~moro/unix-programmer/faq-j_3.html#SEC35

>flock()はBSD起源ですが現在ではほとんどの(但し全てではない)Unixで利用できます。
>単一のホストでは簡単で効果的ですが、NFSでは全く使えません。 これはファイル全体を
>ロックします。
>さらに紛らわしいことに、 ポピュラーなプログラミング言語Perlは
>必要であればそれ自身のflock()関数を実装し、 完全な移植性があるように
>見せかけています。
044344002/03/13 00:06ID:???
とあるソフトでflockが刺さる現象がユーザのところで年に数回発生してて、
lockdを再起動すると回復したりする。 (らしい)
直接の担当じゃないから、ほじってないんで… 謎
0444nobodyさん02/03/13 00:06ID:J00pd5X0
順位をつける明快なアルゴリズムってないですか?
例えば成績データとかで、
ishida,80
inoue,70
gotou,70
satou,65
shibata,90
suzuki,80
のような物があった時
1位,shibata,90点
2位,ishida,80点
2位,suzuki,80点
4位,inoue,70点
4位,gotou,70点
6位,satou,65点
と表示したいのです。
考えれば考える程複雑になっていくので…
0445nobodyさん02/03/13 00:10ID:???
そのリストの最大値求める。
同点を求める。ループ回して見つかった物を次々リストにプッシュすれば良かろう。
処理が終わったら処理後のデータを−1とする。

↑を最大値が−1になるまで続ける。


とかね。ループだらけでシンプルじゃないな。

sortで並べて一つ上のデータとどう得点の場合は上と同じ順位を表示とか。
0446nobodyさん02/03/13 00:37ID:???
そんなに複雑かぁ?
$score = 101;
for($i = $j = 0; $i <= $#r; $i++){
if($r[$i]->[1] < $score){
$j = $i ;
$score = $r[$i]->[1];
}
$r[$i]->[2] = $j;
}
0447パッチ02/03/13 00:38ID:???
$r[$i]->[2] = $j + 1;
0448nobodyさん02/03/13 00:41ID:???
>>446
さっきまでJavascript書いてたの。
で、>>446見たら死ぬほど読みにくいわ。
恐るべし。Perlw
0449nobodyさん02/03/13 00:42ID:???
>>444
$score{$name} に点数が入っていて、100点満点だとします。
while( ($n,$s) = each %score) { $inverse{sprintf("%03d $n",$s)} = undef; }
$rank = 0; $last_score = -1;
foreach(sort {$b-$a} keys %inverse ) {
  /(\d+) (.+)/;
  $rank++ if $1 != $last_score;
  $last_score = $1;
  printf("$rank位,$2,%d点\n",$1);
}
てのはどうでしょう。
045044902/03/13 00:47ID:???
>>449
最初の%inverseへの代入は無駄でした・・・
foreach (sort {$score{$b}-$score{$a}} keys %score) {...}
てすればいいのねー。
045144802/03/13 01:08ID:???
おまえらって、そのていどなんだぁー。
0452448 ◆8hKGWRIE 02/03/13 01:09ID:???
>>451
俺の姿で言いたいことはそれだけかい?
■ このスレッドは過去ログ倉庫に格納されています