Perlコーディング初心者質問スレ Part 48
■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん
2006/04/26(水) 18:00:50ID:RLbnve1J【投稿する際の注意】
質問するときは内容をよく吟味してから投稿してください。
「コマンドの意味がわかんない」とかはマニュアル見ましょう。
回答者さんは何でも屋じゃありません。
1: 自分はこういう事がしたい。
2: それでこんな風にやってみたが・・・
3: こんなエラーが出て上手く行かなかった。
最低でも1と3が無いと誰も答えられないよ。
ソース貼る時は、全角スペースでインデント忘れずに。
良い回答は良い質問から。一緒に勉強しましょう。
過去ログやお勧めサイトは >>2-10
0011nobodyさん
2006/04/26(水) 19:05:38ID:???0013nobodyさん
2006/04/26(水) 20:13:44ID:???>>10
その処理のためにスクリプトが10バイトくらい増えてたりしてw
データ大きい時に使うリファレンスはメモリ使用量じゃなく速度目当ての方が多いんじゃないかな。
0014nobodyさん
2006/04/26(水) 20:40:59ID:???メモリーを節約したいならそんなもんじゃぜんぜん不十分だろ。
リファレンスが必要になる時点でおわっとる。
変数は全部グローバルにして使いまわさないと。
コピーに比べたら関数の呼び出しはめっちゃコスト高いからな。
もちろん配列をループで扱うなんてもってのほか。
似たような処理はコピーペーストで記述したほうが速いぞ。
さらにやるなら変数ひとつについてファイルをひとつ作って
必要になったときのみ読み込むようにすると信じられないくらいメモリーが節約できる。
他にもまだまだあるけどこれ以上の極意はタダじゃ教えられないなー
0015nobodyさん
2006/04/26(水) 20:52:51ID:???0016nobodyさん
2006/04/26(水) 21:14:04ID:???逆にいえばパフォーマンスを下げにくいということ?
たまに処理がクソ重い掲示板をとか見かけるんだけど、あれは何が原因なんだろう。
もちろん同じ鯖上で他の掲示板は速かったりする。
0017nobodyさん
2006/04/26(水) 22:08:45ID:keS5Imx+以上
ハイ次
0018nobodyさん
2006/04/26(水) 22:27:04ID:???0019nobodyさん
2006/04/26(水) 22:35:51ID:???スカラ変数1個のメモリなんて誤差範囲に含まれるくらい
0020nobodyさん
2006/04/26(水) 22:40:24ID:???0021nobodyさん
2006/04/26(水) 22:50:55ID:???掲示板で体感でわかるほどの違いになることなんかないんじゃなかろうか。
たまたま別の処理でメモリー使い切っていたとか無駄な解析で遅くなっているとか。
やたらCSSやJS、画像が多いと体感でもはっきり遅いけどね。
0022nobodyさん
2006/04/27(木) 01:36:01ID:???0024nobodyさん
2006/04/27(木) 10:10:59ID:???0025nobodyさん
2006/04/27(木) 11:54:18ID:???無視しろよ。
0026nobodyさん
2006/04/28(金) 04:16:53ID:maSTbsWh2: for ($a = 0; $a <= f; $a++)
3: ダメポ
0027nobodyさん
2006/04/28(金) 04:27:40ID:???for (my $a = 0; $a <= 0xf; $a++) {
print "$a:(゚д゚)<シメジ\n";
}
# 範囲演算子?
for (0 .. 0xf) {
print "$_:(゚д゚)<シメジ\n";
}
002826
2006/04/28(金) 04:48:31ID:???thx!!
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
じゃなくて
0,1,2,3,4,5,6,7,8,9,a,b,c,d,e
と演算させるには地道に置換しかないですか?
0029nobodyさん
2006/04/28(金) 05:25:00ID:???0030nobodyさん
2006/04/28(金) 06:25:40ID:???for('0'..'9', 'a'..'f'){ ... }
0031nobodyさん
2006/04/28(金) 08:57:45ID:???003326
2006/04/28(金) 16:24:53ID:???0035nobodyさん
2006/04/29(土) 07:14:54ID:???どっちも同じこと出来ますよね?
本にはtrの方が高速だと書いてあります。なら全部trでいいですよね?
変換と置き換えの違いがわかりません。
教えてください。
0036nobodyさん
2006/04/29(土) 08:09:45ID:???使い方次第。
>本にはtrの方が高速だと書いてあります。なら全部trでいいですよね?
何をしたいかによる。
試しにs/// で、変数中に含まれる小文字アルファベットを全部大文字にする
正規表現を書いてみよう。
trだと tr/a-z/A-Z/; なんだけど、違いが分かるかな?
0037nobodyさん
2006/04/29(土) 08:10:16ID:???http://perldoc.jp/docs/perl/5.6.1/perlop.pod#item_s_PATTERN_REPLACEMENT_egimosx
http://perldoc.jp/docs/perl/5.6.1/perlop.pod#item_tr_SEARCHLIST_REPLACEMENTLIST_cds
0038nobodyさん
2006/04/29(土) 09:02:10ID:???0039nobodyさん
2006/04/29(土) 12:25:23ID:???気をつけないと嵌る。
tr/\t\n//; # タブと改行にマッチ
tr/\d\s//; # "d"と"s"にマッチ
0040nobodyさん
2006/04/29(土) 23:34:00ID:???read (STDIN,$buffer,$ENV{'CONTENT_LENGTH'});
read (STDIN,$buf,$ENV{'CONTENT_LENGTH'});
$buf eq '' and die;
$buf = $buffer;
ではなくてもう一度<STDIN>に入力する方法ってありませんか?
0042nobodyさん
2006/04/30(日) 01:07:11ID:???> <STDIN>を一度使うと
使うってどういう意味? 標準入力に出力したいのかな。
> もう一度<STDIN>に入力する方法
STDIN へ出力はできないのでは。
というより、設計を見直した方がよさそう。
0043nobodyさん
2006/04/30(日) 05:58:26ID:???処理する(考慮する)内容が少ないからtrが高速ということか
0044nobodyさん
2006/04/30(日) 06:02:22ID:???そういう仕様です
なので、STDINで読み取ったものを再利用したいのなら一度ファイルに書き戻すか、
サイズが小さいなら読み込んだものを再利用するようにコーディングすればいいです
004535
2006/04/30(日) 07:48:31ID:???s/[a-z]/[A-Z]/;
ですね。違いは・・・カッコ?
>>37
参考ページありがとうございます。
tr///は正規表現を使えないということでいいのでしょうか。
>>38
つまり、探すんじゃなくて見つけたモノを単純に置き換えるということでしょうか。
>>39
なるほど。タブや改行を使えると・・・。でもメタ文字は使えないということですね。
みなさん解説ありがとうごぜーました。
ようやく違いがわかりました。
重複するとこもあるけど、役割はちゃんと違うんですね。
0046nobodyさん
2006/04/30(日) 09:13:52ID:???文字クラス展開の有無なんかより、
バックトラックする必要の無い事の方が大きいと思うよ。
>>45
tr/ab/AB/ に等価なのは
s/[ab]/ $& eq 'a' ? 'A' : $& eq 'b' ? 'B' : $& /eg
004736
2006/04/30(日) 10:54:32ID:???ちっがーう! ちゃんと動かして試してみた?
「g」オプションが無いんですよ。
…というのは嘘で、もし s/// で書くとしたら
s/a/A/g;
s/b/B/g;
(中略)
s/z/Z/g;
ってしないとダメなんだ。全然違うでしょ?
>>45に gつけても、出てくるのは小文字アルファベットを [A-Z]に置換した
ワケワカメな結果だけ。
[A-Z][A-Z][A-Z] [A-Z][A-Z][A-Z] [A-Z]…とか。
004836
2006/04/30(日) 10:59:21ID:???$bar=~ s/[a-z]/[A-Z]/g;
print $bar;
結果:
[A-Z] [A-Z][A-Z][A-Z][A-Z] [A-Z] [A-Z][A-Z][A-Z].
# キャラクタクラスだのパターンマッチだのより先に言うべき事が…(;´д`)
004940
2006/04/30(日) 11:00:50ID:???自分のHPで複数の掲示板を設置しているのですがコメントスパムがひどいんです。
その対策として現在稼動しているCGIにスパム対策を記述したplファイルをrequire '….pl';と読み込ませば
今後の追加対策もplファイルひとつで対応出来ます。
本体のCGIを改造するのは複数あるので困難だし配布先がバージョンアップすると一からやり直しだし、。
という理由で対策用のplファイルで一度<STDIN>読み込んで処理し問題無ければ本体のCGIに戻る→標準入力から呼び出す処理が始まる。
という理由です。
0050nobodyさん
2006/04/30(日) 11:13:20ID:???複数の掲示板って一体いくつあるの?
面倒がらずに改造したものを一つ一つ上書きすればいいじゃん。
'….pl'でコメントスパム対策ができるくらいのスクリプトは書けるんでしょ?
本体の頭でrequireしておいて、<STDIN>の後ろに外部サブルーチン呼び出しを
書くだけだから実質2行の追加で本体改造は終わると思うんだが。
0051nobodyさん
2006/04/30(日) 11:28:56ID:???0052nobodyさん
2006/04/30(日) 12:03:02ID:???改造物なら専用スレできいてほすぃ。
あくまでもPerlコーディング初心者、つまりこれから上達したい人の質問にその道の先輩が
答えるのが本道なわけだし。
0053nobodyさん
2006/04/30(日) 13:42:36ID:???tr/ab/ba/ と s/a/b/g; s/b/a/g; は結果が変わるから
tr/a-z/A-Z/ を s/a/A/g …のように説明するのはどうかと思うんだ。
005447-48
2006/04/30(日) 13:58:12ID:???そりゃ、結果は変わるよね(変換がまとめて行われるか否かってレベルで)。
s/a/A/g; のように26回繰り返せば tr と同じ事ができるよって言いたかったんじゃなくて
s/// と tr/// の用途の違いを見せたかっただけ。
そもそも tr は 0-9 a-z A-Zのように連続している事が保証されている文字グループを
同数の別文字に変換する目的なので、その場合は数の多寡に限らず s/// は使わないのがよい。
とか追記すればよかったかな。
005547-48
2006/04/30(日) 14:09:07ID:???jperlやPerl5.8+UTF8で、漢字の新旧変換とか異体字変換する時に重宝する。
005640
2006/04/30(日) 14:33:27ID:???自作しているPerlのコーディングに関する内容なのでここで質問した次第です。
スレ主1の趣旨とかけ離れていると思いませんでしたし。それにここは人が多そうなので。
どうせならrequire '….pl';1行の改造だけで済ませたいです。
# GETメソッドによるチェックもあるのでCGIの2行目に記述しているから
どういうラッパーなんでしょうか?
パイプを変則的に使えば実現出来るのは知っていますが、うちのプロバイダのサーバでは
パイプが使えないようなんです。
0057nobodyさん
2006/04/30(日) 15:34:27ID:???> 自作しているPerlのコーディングに関する内容
え、自作なの? >>49では
> 配布先がバージョンアップすると一からやり直しだし
って書いてあるけど…。
0058nobodyさん
2006/04/30(日) 15:53:15ID:???例えば本来のSTDINを閉じてIO::Stringにtieするモジュール。
strictじゃない環境で動かすつもりならIO/String.pmに
ttp://search.cpan.org/src/GAAS/IO-String-1.08/String.pm
を置いて、四行目以降をplファイルに突っ込めばOK。
#=======================================
package Hack::STDIN::Seekable;
use strict;
use warnings;
use IO::String;
my $stdin = join '', <STDIN>;
close STDIN;
tie *STDIN, 'IO::String', \$stdin;
1;
#=======================================
…新たに書こうとしてるならこんなのは絶対に使って欲しくないけどね
0059nobodyさん
2006/05/01(月) 00:18:30ID:kok0N6Ezプログラム中でUse::TextChaSenとしても実行されていないようです。
#!C:/cygwin/bin/perl
use Text::ChaSen;
print "hoge";
とするとエラーも何も出ずに終わってしまうのですが、どういうことなのでしょうか?
モジュールが正しくインストールされていないんですかね?
0060nobodyさん
2006/05/01(月) 00:30:02ID:???>>59
> プログラム中でUse::TextChaSenとしても実行されていないようです。
その宣言は間違いかもしれません。一般に、 use Text::ChaSen; かも。
> use Text::ChaSen;
> print "hoge";
> とするとエラーも何も出ずに終わってしまう
モジュールが正しく導入された、正常な状態です。
モジュールのインストールでミスってると、@INCを全部探したけどモジュールのファイルが
見つからんぞ、どないなっとんねん?というエラーメッセージが出るはずなので。
結論としては「何ら問題なくインストールできてる。use するときの書き方を再確認すると安心」
ぐらいじゃないですか?
0061>>60
2006/05/01(月) 00:34:25ID:kok0N6Ezprint "hoge";
とした場合hogeは表示されると思うのですが、それすら表示されないのです。
use Text::ChaSenの行でプログラムが終了してそれ以降の行に進んでいない気がするのですが…
0062nobodyさん
2006/05/01(月) 01:02:08ID:???CGIアクセスが実行されるときは、それが投稿なのか普通にアクセスされただけなのかは判別出来てるよね?
それなら簡単じゃないかと・・・
たとえば
my($spamflag) = 0;
if($in{'exec'} eq 'postmsg'){
require 'denypost.pl';
$spamflag = &denypostcheck($in{'posttitle'}, $in{'posthome'}, $in{'postmail'}, $in{'postbody'});
}
のようにすりゃいいんじゃないのでしょか?
denypost.plは
sub denypostcheck{
だらだら〜あーだこーだ
}
1;
だけ
難しく考えすぎじゃないのかな?
0063nobodyさん
2006/05/01(月) 10:13:04ID:BiGx6+8rforeach $log(@rankpairs){
($jikan,$name,$score)=split(/=/,$log);
if($pair{score}>$score){
push(@newrank,"$hiduke=$pair{name}=$pair{score}");
$check=1;
}
if($check==1){
if($pair{name} eq $name){next;}
}
push(@newrank,"$jikan=$name=$score");
}
得点ランキング用のCGIで、個人の最高得点を記録した後、
ログファイルにある$log{name}データと、フォームから送られた$pair{name]が同じ場合は、
それ以降、同じ名前の人は登録をせずにスルーしたいのですが、どうしてもうまく動いてくれません。
全てが「真」と判断されてしまうみたいで、全て「next」を通ってしまいます。
一体、どこが間違っているのでしょうか? perlの辞典も買ってきて
色々と調べているのですが本当に分かりません。
0064nobodyさん
2006/05/01(月) 10:59:16ID:???ロジックをよく見直せ。
pushした後で名前の値を比較してどーすんだよ。アフォかいな。
0065nobodyさん
2006/05/01(月) 11:19:05ID:BiGx6+8rそれ以降のループで名前の比較をして、nextしているつもりなのですが…。
0066nobodyさん
2006/05/01(月) 11:28:23ID:???foreach $log(@rankpairs){
($jikan,$name,$score)=split(/=/,$log);
if($check==1){
if($pair{name} eq $name){next;}
}
if($pair{score}>$score){
push(@newrank,"$hiduke=$pair{name}=$pair{score}");
$check=1;
}
push(@newrank,"$jikan=$name=$score");
}
でも、順番を変えたら成功しました。
なぜこれだとうまく行くのか、正直まだ理由が理解できていませんが、
>>64、ヒントを下さってありがとうございました。
0067nobodyさん
2006/05/01(月) 12:00:35ID:???そのソースじゃ問題ありそうな悪寒
0068nobodyさん
2006/05/01(月) 12:03:06ID:???掲示板を作っているのですが
openで読み取りの前に読み込むログを
ロックする必要はあるのでしょうか?
0069nobodyさん
2006/05/01(月) 12:11:37ID:???k○ntのロックの仕方は真似しちゃ駄目よ
0070nobodyさん
2006/05/01(月) 12:15:54ID:???ありがとうございます。
0071nobodyさん
2006/05/01(月) 15:50:31ID:???0073nobodyさん
2006/05/01(月) 17:07:02ID:???0074nobodyさん
2006/05/01(月) 17:15:00ID:???0075nobodyさん
2006/05/01(月) 17:15:27ID:???KENT WEB 総合スレ Part2
http://pc8.2ch.net/test/read.cgi/php/1078991985/
0077nobodyさん
2006/05/01(月) 18:08:15ID:???今でもあんな書き方してるんだったら知らん^^;
0078nobodyさん
2006/05/01(月) 18:09:41ID:???0079nobodyさん
2006/05/01(月) 19:50:42ID:???おまえら注目しすぎ。
0080nobodyさん
2006/05/01(月) 19:53:55ID:???008240
2006/05/01(月) 20:23:44ID:???動作確認しました。
個人的に使うだけなので・・・(^^;
稼動中の掲示板にはrequire一行だけしか記述せずに動作させてみたかったんです。
>>40
にもそれらしいことは書きましたが
plファイル抜ける時にreturn $buffer;としてそれを受け取るように稼動中のCGIも改造すれば
すむんですが、こだわってみたかったんです。
だからplファイルはほとんどif文ばかりです。もちろんそれがPOSTとGETなのか動作判定はしてます。
動作的に投稿時の<STDIN>を2回処理する無駄はありますが、体感出来るほどでもないですし。
0083pel
2006/05/02(火) 10:15:11ID:???例えば下記CGIを実行したとき、バックグラウンドでthre2を実行しておき、ブラウザにはすぐthre1を実行した結果としてprintを実行したいのですが、thre2の終了を待たなければ、thre1は実行されないのです。
これではブラウザがハングアップしてしまうのですが、どのようにしたらよいのでしょうか?
perlのforkやDOSのコマンドstartも試したのですが駄目でした。
***************
use v5.8.0;
use threads;
my $thread1 = threads->new(\&thre1, "1");
my $thread2 = threads->new(\&thre2, "2");
$thread1->join;
$thread2->join;
sub thre1() {
print "$_\n";
threads->yield();
}
sub thre2() {
sleep(30);
threads->yield();
}
***************
よろしくおねがいします!
※マルチポストさせていただいています。
http://www.gac.jp/article/index.php?stats=question&category=10&id=17717&command=msg
0084nobodyさん
2006/05/02(火) 11:06:58ID:???全体のコードが長くなっても、ifを使わないで別処理にしていくのでは、どっちがいいんでしょうか?
前者はコードは短くなりますが、頻繁にifを使うので処理が重くなりそうな気がするんですが・・・
0086nobodyさん
2006/05/02(火) 11:10:02ID:???008885
2006/05/02(火) 11:33:29ID:???0089pel
2006/05/02(火) 11:35:57ID:???86>>
UNIXサーバで動いたforkを使ったソースそのままをWindowsサーバで動かしたら、thread同様printされずです。
0090nobodyさん
2006/05/02(火) 11:39:33ID:???0091pel
2006/05/02(火) 12:09:46ID:???(タスクマネジャ参照)
しかし、ブラウザが拘束されて、printされないことが回避できません。
方法知りませんか?
0092pel
2006/05/02(火) 12:11:19ID:???すいません、今テストしたところ、threadは使えてバックグラウンド処理は行えているようです。
(タスクマネジャ参照)
しかし、ブラウザが拘束されて、sleepが終わらないとprintされないことが回避できません。
方法知りませんか?
0093nobodyさん
2006/05/02(火) 12:18:06ID:???0096nobodyさん
2006/05/02(火) 15:30:13ID:???$net_ftp->rmdir('directory');
だと、空じゃないディレクトリは消えないのですが、これを
rm -rf(unix)
rd /s /q(NTのCMD)
みたいなことってできますか?
先にディレクトリの中を空にしてから、cdup()で上がって消すしかないですか?
あと、これはついでなのですが・・・
rmdir(DIR,[RECURSE])
mkdir(DIR,[RECURSE])
の中に入るRECURSEって何を入れたらいいもんなんでしょう。。
0097nobodyさん
2006/05/02(火) 15:46:28ID:???$net_ftp->rmdir('dir', 1);
みたいにしたらディレクトリの中身ごと消してくれる。
とNet::FTPのドキュメントに書いてある。
0098nobodyさん
2006/05/02(火) 16:33:51ID:???そのあたりはドキュメント見ながらやったのですが、
$net_ftp->rmdir('dir', 1);
をやるとエラーが出ます。
Deep recursion on subroutine "Net::FTP::rmdir" at C:/perl/lib/Net/FTP.pm line 612.
となって、100回以上ループしてるようなんです。
1と文字列の'true'は試してみました・・・
0099nobodyさん
2006/05/02(火) 17:55:48ID:???今CGI掲示板をいじっているのですが
foreachの前に配列や変数を空にする場合
よく@xxx=(); $=0;と見るのですが
undefはあまり使わないのでしょうか?
0100nobodyさん
2006/05/02(火) 19:04:32ID:???初期化とは意味が違います
0102nobodyさん
2006/05/02(火) 20:30:46ID:???use strict;
my($test);
$test=""; #初期化
print $test;
undef $test; #削除
print $test;
結果:Use of uninitialized value in print at a.pl line 11.
まぁお好みでいいんじゃね?
0103nobodyさん
2006/05/02(火) 20:32:50ID:???0105nobodyさん
2006/05/02(火) 20:35:43ID:???いや、strictなソースは素晴らしいけど、warningsはマジで要らなくないか?
空の値をprintするだけでも警告出るんだぞ?
0106nobodyさん
2006/05/02(火) 20:36:41ID:???0107nobodyさん
2006/05/02(火) 20:37:40ID:???0108nobodyさん
2006/05/02(火) 20:47:13ID:???0109nobodyさん
2006/05/02(火) 20:51:56ID:???0110nobodyさん
2006/05/02(火) 21:03:44ID:???■ このスレッドは過去ログ倉庫に格納されています