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

Perl 初心者コーナー Part23

■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん03/05/16 11:18ID:zDRBc/j4
いらっしゃーい、Perlのコーディングで困ってる人のスレです。

【投稿する際の注意】
質問するときは内容をよく吟味してから投稿してください。

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

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


CGIだけど、なんか質問ある? Part 10
http://pc2.2ch.net/test/read.cgi/php/1048686475/
【Perl,CGI】参考書籍 第三版
http://pc2.2ch.net/test/read.cgi/php/1030209573/
CGIに依存しないPerlの話題一般/Part2
http://pc2.2ch.net/test/read.cgi/php/1030548610/
スクリプトの改造依頼は、【 スクリプト改造工房 PART 6 】
http://pc2.2ch.net/test/read.cgi/php/1047806915/

過去ログやお勧めサイトは >>2-10
0083nobodyさん03/05/18 00:08ID:???
書き込みモードで開く。
0084nobodyさん03/05/18 00:10ID:aBq13e5f
> 読み込みと書き込みを同時に行おうと
思ってます。

終点のtell(OUT)以下を削除する方法です。
0085nobodyさん 03/05/18 00:10ID:???
ヒマなんで作ってみた
@seed = (0 .. 99);
my %seed;
sub init{#初期化
for(0 .. $#seed){
$seed{$_} = $_;
}
}

sub select{#取り出し
my $num = $seed{int(rand(scalar(keys(%seed))))};
delete $seed{$num};
return($num);
}

&init;
$uniq_num = &select; #コレを繰り返しとな・・・
00868503/05/18 00:12ID:???
>>85 訂正
my %seed;
sub init{#初期化
for(0 .. $#seed){
$seed{$_} = $seed[$_];
}
}
0087nobodyさん03/05/18 00:13ID:???
gensym
0088nobodyさん03/05/18 00:18ID:???
>>82
>seek(OUT,0,0);
これじゃ追記じゃなく上書きじゃないか
0089nobodyさん03/05/18 00:21ID:???
>>88
読み込んだ内容を編集して上書きしたいと思ってます。
0090nobodyさん03/05/18 00:21ID:???
>>82
open(OUT, "+>>file.txt");
0091nobodyさん03/05/18 00:22ID:???
>>89
http://www.rfs.jp/sitebuilder/perl/05/03.html#open
0092nobodyさん03/05/18 00:25ID:???
>>90 >>91
色々助言いただいてありがとうございます。
いじくってみます。
0093nobodyさん03/05/18 00:26ID:???
>>92
っていうか、Win98で鯖を立てることが間違っているのでは
0094nobodyさん03/05/18 00:29ID:???
質問させてもらいます。
自作関数で、引数が不正の場合に、
Perlの文法チェックでエラーを出力させたいのですが、
方法がわかりません・・・
どうすれば文法チェック時に引数のチェックができ、エラーを出せますか?
0095nobodyさん03/05/18 00:37ID:???
>>77
@dat0 = @dat1 = ();
foreach(0 .. 999999){ $dat0[$_] = $_; }
foreach(0 .. 999999){ $dat1[$_] = splice(@dat0,rand($#dat0),1); }
ではだめ?
0096nobodyさん03/05/18 00:41ID:???
>>94
ほっといてもSyntaxErrorになるだろ
不正かどうかのエラー処理はプログラマの責任でやるもの
0097nobodyさん03/05/18 00:51ID:???
>>94
プロトタイプ宣言しろ。

>>96
うぉい。
00988503/05/18 01:05ID:???
ハッシュだと駄目だな・・・

@seed = (0 .. 10);

sub select{#取り出し
  my $key = int(rand(scalar(@seed)));
  my $num = $seed[$key];
  splice(@seed,$key,1);
  return($num);
}

$data = &select;
0099nobodyさん03/05/18 01:09ID:???
>>95
なぜ、そんな巨大な配列を作るんだ?
コストがかかってしかたないと思うが・・・
普通にfor文でぶん回せば良いと思うのだが・・・
0100nobodyさん03/05/18 01:28ID:???
100げと
0101nobodyさん03/05/18 01:43ID:wPiZL/S/
おすすめサイト一覧です☆
http://accessplus.jp/staff/in.cgi?id=10645
http://www.39001.com/cgi-bin/cpc/gateway.cgi?id=neat
http://www.emzshop.com/goodstyle/
0102nobodyさん03/05/18 01:53ID:???
srand();
my @salts = ( "A".."Z", "a".."z", "0".."9", ".", "/" );
my $salt = $salts[int(rand(64))] . $salts[int(rand(64))];

$crypt = crypt($str, $salt);

こういうルーチンだと、暗号化文字列内に「_」は絶対含まれ
ないですよね?
0103nobodyさん03/05/18 01:55ID:Qi8mxUK4
1kbのファイル10個を1つずつopenしてprintしてcloseするのと、
10kbのファイルをopenしてprintしてcloseするのは
どっちが処理に時間がかかるのでしょうか?
0104nobodyさん03/05/18 01:59ID:???
だんぜん前者
0105nobodyさん03/05/18 03:23ID:???
>>102
どんなルーチンかは関係なくcryptの戻り値に「_」が含まれることはない
そもそも、そのルーチンってsaltをランダムにしてるだけじゃないの
01068303/05/18 05:27ID:???
>>84
改めて開くんだよ。それくらい理解しろよ。
0107nobodyさん03/05/18 05:30ID:???
>>93
>>82は鯖を立てているとは言っていないんだが。
0108nobodyさん03/05/18 06:12ID:???
>>105
ボケボケでした。ご指摘有難うございます。
貴重なご返答有難うございました。
0109nobodyさん03/05/18 07:34ID:K+Hh/k3W
ム板から追い出されてしまいました・・。

すみません、質問です。
csvファイルの一番上から順に1レコード読み込んで、$idと$keycodeが等しければ
それぞれ変数に代入する、という検索の部分なのですが、$idが奇数、又は偶数だ
と(csvファイルのレコード数が奇数か偶数かによる)検索失敗しまいます。
尚、$data = <IN>;の部分は、手元の本だと$data = $_;になっています。これだと
全く代入されません。
csvファイルに問題は無いと思います。お願いします。

$match = 0;
open IN,"log.csv";
while((<IN>)and($match == 0)){
$data = <IN>;
chop $data;
($keycode) = split(/\,/,$data);
if($keycode == $id){
($keycode,$flg,$mailadd,$name,$title,$comment) = split(/\,/,$data);
$match = 1;
}
}
close IN;
0110nobodyさん03/05/18 07:40ID:???
尼寺へ行け
0111nobodyさん03/05/18 07:43ID:???
っていうか、while(<IN>) の中でなんでまた<IN>を読んでるの?
0112nobodyさん03/05/18 08:04ID:???
>>111
仕様です。
0113nobodyさん03/05/18 08:18ID:???
>>109
これでどうだ? $id($keycode)は1バイトであるという前提。
ちなみに見つからない場合は$keycodeが未定義になる。

undef $keycode;
open(IN, "log.csv") or die;
while (<IN>) { chomp; /^$id/ and last }
($keycode, $flg, $mailadd, $name, $title, $comment) = split /,/ if $_;
close(IN);
0114nobodyさん03/05/18 10:11ID:???
>>113
whileのなかでchompする意味なし
0115nobodyさん03/05/18 10:40ID:???
>>109
>手元の本だと
タイトル希望。
0116nobodyさん03/05/18 12:35ID:???
>>114
そうでもないぞといってみる。
0117nobodyさん03/05/18 13:06ID:???
文字列を暗号化してファイルに記録したいんだけど、
どんな方法がありますか?
0118nobodyさん03/05/18 13:24ID:???
暗号になってればいいだけならmd5とか
0119nobodyさん03/05/18 13:34ID:???
>>109
俺も本のタイトルが知りたい。どんな糞かと。
0120nobodyさん03/05/18 14:23ID:???
CGIの本はいっぱい出てるからね
012111303/05/18 15:56ID:???
>>114
その通りなんだが、splitを無理矢理1行で書きたかったんでああなった。
実行効率を考えたら、ループの外でやったほうがいいね。
添削サンクス
0122nobodyさん03/05/18 16:06ID:???
文字列の中から特定の文字がいくつあるか判定したいのですが、

$count += ($com =~s/test//g);
このような方法しか思いつきません。
もっとスマートなやり方を教えて頂けないでしょうか?
0123nobodyさん03/05/18 16:25ID:???
>>122
それ以上スマートな方法があるのかと。
と言うか、君の言うスマートってどんな意味?
0124nobodyさん03/05/18 16:33ID:???
>>122
1文字だけのカウントなら tr/文字/文字/ というのがあるけど、
文字列だとそれが一番シンプルにできるんじゃない?
0125nobodyさん03/05/18 18:07ID:rnV9NZSQ
perlの正規表現についてくわしく説明されているサイトってありませんか?
0126nobodyさん03/05/18 18:12ID:???
>>125
そのぐらい探せよ・・・
0127nobodyさん03/05/18 18:21ID:OtatQ8zk
★大人になってから★
http://yahooo.s2.x-beat.com/linkvp/linkvp.html
0128nobodyさん03/05/18 18:33ID:???
>>125
http://www.din.or.jp/~ohzaki/regex.htm
http://www5a.biglobe.ne.jp/~n_rieko/perl/8.htm
0129nobodyさん03/05/18 18:47ID:???
>>125
当然Google等で調べたんでしょう。
その結果どのページを見ても理解できなかった、と。
諦めなさい。君には無理だ。
0130nobodyさん03/05/18 18:49ID:???
>>123-124
置き換えを使わずにできるかと思ってました。
$count += ($com =~/test/g); とか・・・
レスして下さってありがとうございます。
0131nobodyさん03/05/18 19:25ID:???
@lines[0..1000] = `"/usr/local/bin/wget" -q -O - $URL` or die;

こんな事してるんですがどうやら$URLが長いと途中でちょん切れるようです。
"11223344556677889900" → "11223344556677889"
解決できますか?
0132nobodyさん03/05/18 21:57ID:???
>>130
できるよ
$count++ while $com =~/test/g;
013310903/05/18 22:15ID:???
レスありがとうございます。
>111
$data = <IN>; の部分のことでしょうか?
本では$data = $_;となっていますが、これだと全く代入されません。
自分で書き直しました。
マッチしてるかどうか調べる処理の前に余計に読み込んでいるから
交互に検索失敗・成功してしまうのでしょうか?

>113
ありがとうございます。試してみます。
尚、$keycode、$IDともに2桁以上の場合があります。

0134nobodyさん03/05/18 22:29ID:???
思った事。
>>1-10
のところに、かなり良いサイト書いてある事に今さら気付いた。
十分立派なリンク集。
0135nobodyさん03/05/18 23:00ID:???
でも質問するやつは絶対に見ないから大して役に立たないリンク集
0136nobodyさん03/05/18 23:07ID:???
I will use Google before asking dumb questions.
013713103/05/18 23:08ID:???
@lines[0..1000] = `/usr/local/bin/wget -q -O - $URL` or die;
の間違いでした、すみません。

$URLの文字数が59ぐらいまでは大丈夫なんですが、68になるとダメです。
013813403/05/18 23:11ID:???
>>135
日本語サイトを順番に見ていってるけど、グット!
大変有益な情報が書いてある。読んでて面白かった。
(知ってるサイトが多かったけど)
0139nobodyさん03/05/19 01:05ID:UimoOLmz
open(FILE, "+< $logfile");
@data = <FILE>;
unshift(@data,"$year年$mon月$day日(@youbi[$wdy]),$hour時$min分$sec秒\n","$referer\n","$host\n","$ENV{'REMOTE_ADDR'}\n","$ENV{'HTTP_USER_AGENT'}\n\n");
flock(FILE,2);
seek(FILE,0,0);
print(FILE "@data\n");
flock(FILE,8);
close(FILE);

こういうアクセスログをつかってるんですけど、
datファイルは最初の行以外に半角スペースができるのですが、なぜでしょう?
0140動画直リン03/05/19 01:08ID:IEVyzYan
http://homepage.mac.com/hitomi18/
0141nobodyさん03/05/19 01:11ID:???
>>139
print(FILE "@data\n");
0142nobodyさん03/05/19 01:12ID:???
>>139
>print(FILE "@data\n");

""の中でリストを展開すると、リストの各要素が" "(半角スペース)で区切られて
出力されるから。
print(FILE, @data); のようにすれば大丈夫なはず。
0143_03/05/19 01:12ID:???
( ´Д`)/< 先生!!こんナのが有りますた。
http://togoshi.ginza.st/mona/mona05.html
http://www.togoshi.ginza.st/mona/
http://www.togoshi.ginza.st/mona/mona03.html
http://togoshi.ginza.st/mona/mona02.html
http://www.togoshi.ginza.st/mona/monaz08.html
http://togoshi.ginza.st/mona/mona06.html
http://www.togoshi.ginza.st/mona/mona10.html
http://togoshi.ginza.st/mona/mona04.html
http://www.togoshi.ginza.st/mona/mona07.html
http://togoshi.ginza.st/mona/mona01.html
http://www.togoshi.ginza.st/mona/mona09.html
0144nobodyさん03/05/19 01:13ID:UimoOLmz
>>141
え?どういうことでしょうか?
014514203/05/19 01:13ID:???
間違えた。FILE の直後の , は不要だった。スマソ
0146nobodyさん03/05/19 01:14ID:UimoOLmz
>>142
できました。ありがとうございました。
0147nobodyさん03/05/19 10:32ID:/e0GDQuH
#------------------------------------------------------------
&HtmlError($errormessage); #$errormessage自体はEUC

sub HtmlError($HtmlErrormessage){
my $HtmlErrormessage = $_[0];
&jcode::convert(*HtmlErrormessage, "sjis");
print $HtmlErrormessage;
exit;
}


#------------------------------------------------------------
が、なぜかEUCでブラウザに出力されてしまいます。
ずーっと見て悩んでたのですが、わかりません。
どこがいけないのでしょうか?

なお、下記はちゃんとSJISで出力されます。(あたりまえですが)
まさか、関数に文字を引き渡すことと、文字コードって関係あるんでしょうか?
(だとしても、ちゃんとprintする直前にsjisに変換してるし・・・)

&jcode::convert(*errormessage, "sjis");
print $errormessage;
0148nobodyさん03/05/19 11:05ID:???
>>147
>&jcode::convert(*HtmlErrormessage, "sjis");
レキシカル変数では型グロブは使えない

&jcode::convert(\$HtmlErrormessage, "sjis");
014914703/05/19 11:08ID:???
>>148
あいや、まったく未知でした。ありがとうございます。
0150nobodyさん03/05/19 11:13ID:???
>>149
つか、なんでjcodeを古いやり方で使ってる奴ばっかなの?
しかもなんか中途半端に::で区切ってるし。
0151nobodyさん03/05/19 11:48ID:???
( ´・∀・`)へー
0152nobodyさん03/05/19 12:18ID:???
>>150
配布されてるCGIがそう書いてるのを真似してるのかもね。
で、ライブラリの書式が変わったのは理解できても、型グロブのほうは理解できないので
そのまんま。とりあえず動くからいいや、みたいな。
0153nobodyさん03/05/19 12:21ID:???
>>150
( ・∀・)つへぇ〜 へぇ〜 へぇ〜 へぇ〜 へぇ〜 へぇ〜 へぇ〜
015414703/05/19 12:26ID:???
>>152
ビンゴ。
0155nobodyさん03/05/19 12:26ID:???
if (条件式) に使う条件式で、
同じ条件式を何回もいろんなところで使っているのですが、
こういう条件式自体を変数みたいに?1箇所にまとめることって可能なのでしょうか?
0156nobodyさん03/05/19 12:34ID:???
>>155
可能。
0157nobodyさん03/05/19 12:41ID:???
どうしたらいいか聞けよ。
$hoge = "doredore";
if (&matomere) {print "Ok!\n";}
sub matomere { return '$hoge =~ /ahodoredorebaka/' }
0158nobodyさん03/05/19 12:59ID:???
これだけヒント与えたのに自分で解決できないのか。ほれ。
$hoge = "doredore";
if (&matomere) {print "Ok!\n";}
sub matomere {if ($hoge =~ /ahodoredorebaka/) {return 1;} else {return 0; }}
#if ($hoge =~ /ahodoredorebaka/) {print "OK!\n";}
0159nobodyさん03/05/19 13:03ID:???
メールアドレスって
日本語氏名 <[email protected]>
ってなっていることがありますよね。

ここからメールアドレス部([email protected])のみを正確に取り出したいのです。
この処理を行ってくれるperlモジュールをご存じの方いませんか?
0160nobodyさん03/05/19 13:06ID:???
#mailaddr.pm
$mailaddr=~s/(.+)</$1/;
0161nobodyさん03/05/19 13:11ID:???
うまく行かない場合はうまく行かないと言え。
$mailaddr=~s/.+<(.+?>/$1/;
0162nobodyさん03/05/19 14:55ID:???
($address) = $str =~ /<(.+)>/;
なるべくロングに取得
0163nobodyさん03/05/19 15:03ID:???
>>132
そのような方法があるとは思いつきませんでした・・・
ありがとうございます!
0164nobodyさん03/05/19 15:16ID:???
>>157の方法だと、

our $hoge = "doredore";
if (eval matomere()) {print "Ok!\n";}
sub matomere { return '$hoge =~ /ahodoredorebaka/' }

(気持ち悪い)


>>158は冗長。
sub matomere {$hoge =~ /ahodoredorebaka/}
これでいい。

でも、こういう関数は一部でしか使わないだろうから、ローカル関数化する。
local *matomare = sub { $hoge =~ /ahodoredorebaka/ }
こうしましょう。
0165nobodyさん03/05/19 15:17ID:???
おっと。セミコロンが必要。
local *matomare = sub { $hoge =~ /ahodoredorebaka/ };
0166nobodyさん03/05/19 15:26ID:???
同じ条件式っていうことはその結果は決まってるはずだな。

多分、、質問はそういう意味ではなくて、、むむむ、クロージャーか。

my $expr = sub {
my $hoge = shift;
return $hoge =~ /hogehoge/;
}
print 'TRUE' if $expr->('hogehogehoge');

こうしたいのか?
016715903/05/19 15:37ID:???
>>160
ありがとうございます。でも機能しません。("<"が一つ取れるだけ)

>>161
ありがとうございます。でもシンタックスエラーです。

>>162
ありがとうございます。動きました。

0168nobodyさん03/05/19 16:34ID:???
>>75

超遅レスで申し訳ないが。。
その文字がエンコードされて送信されてくるかどうかは
実はクライアント(ブラウザ)に依存する罠・・・

昔携帯向けのサイトを作ったときハマッタ。
i-modeではエンコードされないのにJ-skyではエンコードされて来て
気が付くのに2晩かかったよ。

全てのクエリーストリングをデコードくぐらせるのが吉。。。
016913103/05/19 16:36ID:???
>>137はやはり無理なのでしょうか。
0170Perl/CGI03/05/19 18:04ID:Ob4BWAW/
CGIで、ファイルに書き込みしたいのに、どうしてもこのopen行が原因でエラーになります。
本とかで調べてもあってるはずなのになんでおかしいのでしょうか。

open(INIFILE,"+<$fileini");
close(INIFILE);
ローカルでこの行が入ってるファイルをテストしてみたら、
Unterminated <> operator
というエラーがでてとまってしまうんです。
この行を含まなかったらぜんぜん問題なしなんですけど、この行で全部とまってしまってるんです。
このエラーはいったいどう対処したらいいのか、そしてどう改善すればいいのか教えていただけないでしょうか?
0171nobodyさん03/05/19 19:58ID:???
>>169
おまえな、それが一体どこがPerlの質問なんだよ。
いい加減気付けよ。
0172nobodyさん03/05/19 20:06ID:???
>>170
それはファイルを読み書き両方ができるようにオープンしているようだが、
ファイルハンドルから察するに読み込むだけでいいんではないか?

なら、
open ( IN, $file );
open ( IN, "<$file" );
のどちらかで済む話じゃないか?

まあ、フリーのスクリプトか自作かは知らんが、前後の状況がわからんからこれ以上はいえないが。
017313103/05/19 20:24ID:???
>>171
すいませんでした・・・
0174nobodyさん03/05/19 20:26ID:???
>172
INFILEじゃなくてINIFILEだから書き換えたりもするんじゃない?
0175nobodyさん03/05/19 20:30ID:???
>170
ttp://www.google.com/search?as_q=Perl+Unterminated+%3C%3E+operator+&num=100&hl=ja&ie=UTF-8&oe=UTF-8&btnG=Google+%E6%A4%9C%E7%B4%A2&as_epq=&as_oq=&as_eq=&lr=lang_ja&as_ft=i&as_filetype=&as_qdr=all&as_occt=any&as_dt=i&as_sitesearch=

その前の文で"の閉じ忘れとかないか?
0176nobodyさん03/05/19 20:58ID:???
質問させていただきます。

$IPAD = $ENV{'REMOTE_ADDR'}
などとして得たアドレスを2進数に変換したいのです、ご指導お願いします。

例えばアクセスした人のアドレスが
202.213.37.74だった場合、
11001010110101010010010101001010
という風に変換させたいのですが、perlでスッキリかくには
どのようにすればいいのでしょうか?

お手すきな方、宜しくご指導お願いします。

0177nobodyさん03/05/19 21:36ID:???
>>176
$num="202";
$bits = unpack "B8", chr($num); # $bits=11001010
0178nobodyさん03/05/19 21:45ID:???
>>176
参考に
http://www.mikeneko.ne.jp/~lab/perl/numerical_transform/
0179nobodyさん03/05/19 21:54ID:???
>>176
$bits = join('', map { unpack('B*', chr) } split(/\./, $IPAD) );
018017603/05/19 22:53ID:???
>>177-179
ご指導ありがとうございます。

>>178のページを参考に自分でやって成功したのですが、
>>179さんの方がスッキリしてるので、こちらを使わせていただきます。
助かりました、ありがとうございます。
0181nobodyさん03/05/20 05:07ID:???
現在perlでRPG作ってます。CGIで相手端末は携帯です。
データは全てサーバーに保存させています。

で、ちょっと効率の良い処理が思いつかないので質問に来ました。
まず、
●武器などのデータはテキストでデータ保存した方が良いでしょうか?
●それとも、perl記述内で武器の効果や、強さ、金額などを直接定義したほうが良いでしょうか?

また、武器によって攻撃力が変わるわけですが、
●起動ごとに攻撃力を算出させた方が良いでしょうか?
●それとも算出された攻撃力はそのままテキストデータに保存してしまった方が良いでしょうか?
俺としては前者のほうが、バグが出にくく、管理もしやすいのですが負荷が多くかかりそうな気がします。

俺は、プログラム経験が浅いのでこの辺の判断がつきません。汗
経験の長い皆様にアドバイスを頂きたくてやってきました。
よろしくお願いします。
0182nobodyさん03/05/20 05:32ID:???
う〜ん、やっぱこんな一部的なコト書いても誰も答えられないよね。汗
自分で思考錯誤して頑張ります。
■ このスレッドは過去ログ倉庫に格納されています