Perlについての質問箱 18箱目
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2005/07/20(水) 05:15:36"There's more than one way to do it" ということで、Perlの奥深さについて皆で語り合い、追求してまいりましょう。
CGIについての質問は板違いです。WEBプログラミング板でどうぞ。
CGIとPerlの区別がつかない人もWEBプログラミング板に行ってください。
(WEBプログラミング板 http://pc8.2ch.net/php/ )
CGIの質問は答えがPerlと全然関係ない話に帰着する場合が多かったりするのでWEBプログラミング板に行って聞いたほうが得ですよ。
このスレでは(CGI以外の)純粋にPerlのみに関係する質問を取り扱っていこうと思います。
http://www.perl.org/get.html
● 2005/03/17現在の最新版: 5.8.7
● 2005/03/17現在の開発版: 5.9.2
0656デフォルトの名無しさん
2005/09/04(日) 21:01:070657デフォルトの名無しさん
2005/09/04(日) 21:02:53質問あんま読んで無かっただけじゃないかと…
0658デフォルトの名無しさん
2005/09/04(日) 21:23:27そこで次のサブルーチンを作成してみました
[ $Trafic_Timeout ]秒間に [ $Trafic_min_limit ] バイト転送したら転送量エラーと表示したいとして
&TraficPlus(画像サイズ);
って感じで呼び出したいと思っています。
全くスマートなプログラムではありませんが、これでいけると思ってやった見て、何度か改良しましたがうまくいきません。
どなたか改良又は知恵をかしていただけませんか?宜しくお願いします。
sub TracficPlus{
$plus = $_[0];
my $size;
&filelock('tr.lock');
$Trafic_min_limit = 202400;
$Trafic_Timeout = 60;
my $nowtime=time;
open(IN,"time.trafick");$mtime = <IN>; close(IN);
open(IN,"now.trafick");$total = <IN>;close(IN);
$time = $nowtime - $mtime ;
if($time > $Trafic_Timeout){
$total = 0;
open(IN,">time.trafick");print IN $nowtime; close(IN);
}
$total += $plus ;
open(IN,">now.trafick");print IN $total;close(IN);
open(IN,"total.trafick");$ttt = <IN>;close(IN);
$ttt += $plus;
open(IN,">total.trafick");print IN $ttt;close(IN);
&fileunlock('tr.lock');
if($total > $Trafic_min_limit){&Error($Limit);}
return $size;
}
0659デフォルトの名無しさん
2005/09/04(日) 22:07:470660デフォルトの名無しさん
2005/09/04(日) 22:09:010661デフォルトの名無しさん
2005/09/04(日) 22:13:42ふざけてないで教えてくれよ!!
マニュアル見んのめんどくせえんだよ!!!
0662デフォルトの名無しさん
2005/09/04(日) 22:15:27CGIについての質問は板違いです。WEBプログラミング板でどうぞ。
CGIとPerlの区別がつかない人もWEBプログラミング板に行ってください。
(WEBプログラミング板 http://pc8.2ch.net/php/ )
0663デフォルトの名無しさん
2005/09/04(日) 22:19:51了解です
0664デフォルトの名無しさん
2005/09/04(日) 22:39:11> マニュアル見んのめんどくせえんだよ!!!
英語のマニュアル読めないんだよ!と正直に言えば
教えてもらえるかもしれないのに
0665デフォルトの名無しさん
2005/09/04(日) 23:45:11つ while(1){}
0666デフォルトの名無しさん
2005/09/04(日) 23:59:590667デフォルトの名無しさん
2005/09/05(月) 00:24:13と
for (;;) {〜}
っておんなじだよね?
0668デフォルトの名無しさん
2005/09/05(月) 00:25:040669デフォルトの名無しさん
2005/09/05(月) 01:09:38おんなじだよ。
> cat test.pl
while(1){1}
for(;;){1}
> perl -MO=Deparse test.pl
while (1) {
'???';
}
while (1) {
'???';
}
test.pl syntax OK
0670デフォルトの名無しさん
2005/09/05(月) 01:13:13とすれば、最初から while (1) {} と書いたほうが良いのかな
0671デフォルトの名無しさん
2005/09/05(月) 07:07:39意味は同じだが、while(1) の方がより自然言語に近いからベター。
for(;;) って書く香具師、キライ。
0672デフォルトの名無しさん
2005/09/05(月) 07:35:320673デフォルトの名無しさん
2005/09/05(月) 08:43:440674667
2005/09/05(月) 08:44:10ありがと。普段はwhile(1)って書くけど、web上で見つけたコードでfor(;;)を使ってるコードがあって気になってた。
つーか、
perl -MO=Deparse
こういうやり方あったのか。知らなかったから勉強になった。thx.
0675デフォルトの名無しさん
2005/09/05(月) 11:21:18おもすれーこれ
0676デフォルトの名無しさん
2005/09/05(月) 14:19:190677デフォルトの名無しさん
2005/09/05(月) 15:43:55while(1)が正解さ。
forはね、何かをカウントする時に使う。って使い分けが読みやすくす秘訣。
0678デフォルトの名無しさん
2005/09/05(月) 15:46:470679デフォルトの名無しさん
2005/09/05(月) 16:33:040680デフォルトの名無しさん
2005/09/05(月) 16:33:31それは、よっぽどのヘタレコンパイラ。
今時のちゃんとしたコンパイラなら、Warningなど出ない。
0681デフォルトの名無しさん
2005/09/05(月) 16:48:40(#define forever for(;;) でも同じ)
ちなみに俺は書かない。
0682デフォルトの名無しさん
2005/09/05(月) 16:56:23俺も書かない。単なるアホだと思う。
でもそれ、Perlがやってることに非常に似てる。
「ここで "is" って書く代わりに、"are" って書けたら自然で良くね?」
「いいねぇ、追加しちゃえ。」
「ジャーン!Perlは更に自由度を手に入れました!どっちも同じ意味ですが。」
0683デフォルトの名無しさん
2005/09/05(月) 16:57:09Perlについての質問箱です。
Perlについての質問箱です。
0684デフォルトの名無しさん
2005/09/05(月) 18:30:540685デフォルトの名無しさん
2005/09/05(月) 19:04:49しかし、Perlほど英文ぽさを意識しておきながら
そこで「複数のブツ」にもisしか使えないとなると、
それはそれで思想的な一貫性に欠ける気もするし、難しいところだなー。
0686デフォルトの名無しさん
2005/09/05(月) 20:28:080687デフォルトの名無しさん
2005/09/05(月) 22:15:34プリプロセッサのマクロで気分で変更してます><
0688デフォルトの名無しさん
2005/09/05(月) 22:18:27宗教戦争に負けないような、強い自己を持ちましょう。
0689デフォルトの名無しさん
2005/09/05(月) 22:23:00至言だね。
0690デフォルトの名無しさん
2005/09/05(月) 22:24:41print($a,$b,$c);
と
print $a,$b,$c;
って何が違うの?
0691デフォルトの名無しさん
2005/09/05(月) 22:35:14test.cは読み書き可能な状態なのにundefineが返してくるのは何で?
0692デフォルトの名無しさん
2005/09/05(月) 22:38:300693デフォルトの名無しさん
2005/09/05(月) 22:53:090694デフォルトの名無しさん
2005/09/05(月) 23:12:000695デフォルトの名無しさん
2005/09/05(月) 23:13:51もう一度自分の質問を点検せよ。
0696デフォルトの名無しさん
2005/09/05(月) 23:17:04ミス
open関数によって作成されたファイルの権限ってどうなってるの?
0697デフォルトの名無しさん
2005/09/05(月) 23:25:22PostgreSQLを使用するスクリプトでPg.pmが使われているのを
DBIを使うように書き換えていきたいんですが。
0699デフォルトの名無しさん
2005/09/06(火) 00:17:07man umask
0700デフォルトの名無しさん
2005/09/06(火) 00:30:48そのスクリプトがDBD::Pg を直接叩いてるなら、狙ったのは速度でしょうね。
スクリプト --> DBI(Perl) --> DBD::Pg(Perl, XS) --> Postgres
スクリプト --> DBD::Pg(Perl, XS) --> Postgres
DBIで書き換えるのは賛成です。
メソッド名がDBIと揃ってるんじゃないかと思うので、そんなに労力要らないハズです。
0701デフォルトの名無しさん
2005/09/06(火) 01:18:110702デフォルトの名無しさん
2005/09/06(火) 01:28:13おい。DBD::PgじゃなくてPgだろ。
0703デフォルトの名無しさん
2005/09/06(火) 02:50:390704619-620
NGNG>>627
ありがとうございます。
やっと解決しました。
>>620に載せたスクリプトには問題はありませんでした。
ただ、Cronの実行の仕方に問題があったのでした。
【失敗】
10 * * * * /home/user/test.pl
【成功】
10 * * * * /home/user/test.pl < /dev/zero > /dev/null 2>&1
最後の/dev/null・・・の部分はログを残したい場合は、そのファイルを指定します。
Cronのあるバージョンからこのように明示しなくてはならなくなったようです。
このページを参考にしました。
http://www.turbolinux.co.jp/support/document/knowledge/639.html
遅くなりましたが解決しました。
ありがとうございました。
0705デフォルトの名無しさん
2005/09/06(火) 18:00:260706デフォルトの名無しさん
2005/09/06(火) 19:44:21ってやって意味あるの?
やらないのと何が違うのか具体的に教えて。
0707デフォルトの名無しさん
2005/09/06(火) 19:46:55Windows(ActivePerl)だと問題が発生する
Cygwin/UNIXじゃ大丈夫だけどな
Windowsはテキストファイルとバイナリファイルを区別してるから
バイナリファイルを読み込むときはbinmodeしないとファイルを正しく読み込めない
とラクダ本に書いてあります
ラクダ本ぐらい買えよ
0708デフォルトの名無しさん
2005/09/06(火) 20:26:541行でデータが羅列されているテキストファイルに改行をいれたいのです。
例えば X Y Z X Y Z X Y Z というファイルを
X Y Z
X Y Z
X Y Z
にしたいのです。、一応動くのですが、なんとなく遠回りしてる気がして・・・・
データ数も多いので、処理速度を改善できないかとご相談を。
もしよろしければ、間違った文法のご指摘等もよろしくお願いします。
open(FILE, "$file") or die "ERROR:そのようなファイルはありません。\n";
while(<FILE>){
@gyo = $_;
}
$all = @gyo[0];
$outfile = "out.txt";
open(OUTPUT, ">>$outfile");
$count = 1;
while($count < 33697){
$tests = substr($all,0,85);
$testss = $tests . "\n";
$all =~ s/$tests//g;
push @alls ,$testss;
$count = $count + 1;
}
foreach(@alls){
print OUTPUT "$_";
}
close(OUTPUT);
close(FILE);
0709デフォルトの名無しさん
2005/09/06(火) 20:34:28@gyoにファイルのデータをためこむとメモリ使用量が増大して実行速度は遅くなるだろうね
普通はbufferとか変数つくって1024byteごと読むとかがセオリーだけど
その処理なら
一行よんで一行(分割した行)を書き込むという処理がベストかと
0710デフォルトの名無しさん
2005/09/06(火) 20:40:00標準で有効になっているエンコード変換(の一種)を抑止する指示。
この変換は、OS標準のテキスト形式をPerlが想定するテキストストリーム形式に変換する。
OSの標準形式がPerlが想定するテキストストリーム形式と等しい場合は、何も起きない。
極端な例.
perl -e "use encoding 'euc-jp';while(<STDIN>) {print}" <in.euc >out.euc
perl -e "use encoding 'euc-jp';binmode(STDOUT);while(<STDIN>) {print}" <in.euc >out.utf8
perl -e "use encoding 'cp932';while(<STDIN>) {print}" <in.sjis >out.sjis
perl -e "use encoding 'cp932';binmode(STDOUT);while(<STDIN>) {print}" <in.sjis >out.utf8
これは、テキストモードだと文字コード自体の変換を伴う例。
binmode時は、文字コードの変換も止まっている事がわかると思う。
警告が邪魔なら、printの前にuse bytes; 入れれ。
0711708
2005/09/06(火) 21:11:53あ、元のファイルは1行しかないんです。
85文字目までが1行の単位でそれが33697回繰り返してある1行のファイルなんです。
最初のファイルから1行読むってのは85文字目まで読むってことですか?
そうすると次は85〜170まで次は〜って感じですか?
0712デフォルトの名無しさん
2005/09/06(火) 21:14:26Whileじゃなくてreadで85byteづつ読んだほうがいい
0713デフォルトの名無しさん
2005/09/06(火) 21:32:29while(<FILE>){ chomp; print OUTPUT $line,"\n" while ( $line = substr( $_, 0, 85 , q[] ) ) }
0714デフォルトの名無しさん
2005/09/06(火) 21:38:58約 3MB のファイルか。
メモリ利用の効率を無視できるなら、それくらいの容量なら、
今のままの一気に読み込む富豪的アルゴリズムでもいいと思うけどね。
(目的と、ファイルサイズがどれくらいになりうるかで
決めるといいかも。)
フィールド長(85バイト)が決まっているなら、
read で書いても簡単に書けると思うし、
不定でもバッファを用意すればいいね。
>>708のコードは次のように簡潔に書けるから、参考になりそうならどうぞ。
メモリ効率等は改善してないが、可変フィールド長には対応。
open(IN, $file);
my @data = split(/\s+/, <IN>);
close(IN);
open(OUT, ">>$outfile");
for (my $i=0; $i<@data; $i+=3) {
print OUT "$data[$i] $data[$i+1] $data[$i+2]\n";
}
close(OUT);
0715デフォルトの名無しさん
2005/09/06(火) 22:26:01while ( @data ){
printf ("%s %s %s\n" , ( shift @data, shift @data, shift @data))
}
になるのかな?
for(;;) というよりも添字がごちゃごちゃしてて嫌い。
0716デフォルトの名無しさん
2005/09/06(火) 22:29:39レスありがとうございます。
大体3MB弱のファイルなのですが、これが400ファイルほどあって。。。
出来るだけ処理速度を上げたいと思いまして。。。
改善の余地としては
@gyoのところで全部読まず1行づつreadで読み書きするようにするとメモリ使用量が少なくてすむ!
という感じですね。
readというものを知らなかったのでこれを使って少し改善してみたいと思います。
>>713さんのだと1行で出来ちゃうのですか?
私にはどんな処理を行っているかすぐに出てきませんOTZ
勉強していろいろ試してみたいと思います。
私の最初の記述でも>>714さんの位短く書けてしまうのですね。
参考にさせていただきますφ
0717デフォルトの名無しさん
2005/09/06(火) 22:36:03こういう場合、ディスクのIOの方がネックになるのでreadでチマチマ読むより一気にメモリに読み込んで処理した方が速いんじゃなかろうか?
この程度だったらたいした差にはならないだろうけど。
0718デフォルトの名無しさん
2005/09/06(火) 22:43:43気にしなくていいんじゃないかと。
0719デフォルトの名無しさん
2005/09/06(火) 22:45:12perl -e 'local $/ = \85; print map "$_\n", <>' file1 file2 file3 ... > splited.log
0720デフォルトの名無しさん
2005/09/06(火) 23:00:40単純に処理速度を上げたいだけなら、717も書いているが
ファイルを一気に読み込むコードのままでもOK。
さらに処理速度を上げたいなら、
例えば ファイルを 100 個ずつ個別に処理し、
最後に結合するなども。
(要するに並列処理を。)
>>719
ワロタ
これで入力ファイルを1つずつにして、シェルスクリプトでファイルを1つずつ渡してやれば
十分現実的だね。
for i in file*.log; do perl -e 〜 $i >> splited.log; done
0721デフォルトの名無しさん
2005/09/06(火) 23:00:42いや、マジで。
$/ に\数字使うって知らなかったよ。
map でなく、普通に while 使って
perl -ne 'BEGIN{$/ = \85}; print $_,"\n"' file1 file2 file3 ... > splited.log
で超富豪からちょっと慎ましく。
0722712
2005/09/06(火) 23:03:38-n オプション付けてるんでwhileループは省略してます
0723722
2005/09/06(火) 23:17:41712 と 721 間違えた。
ついでに 3M*400 = 1.2G となるとやっぱりネックはディスクへのアクセス。
out.txt を読み込みファイルと別のディスクにすると速くなるはず。
それと、100個ずつ並列処理なんかさせるとディスクのアクセスが不連続になって逆に遅くなるのでは?
0724デフォルトの名無しさん
2005/09/06(火) 23:23:53「すれ立てるまでもない質問はここで 第69刷」スレの921,925で質問していた者ですが
こちらのスレが適しているということで来ました。
元々他スレの話題で大変恐縮なのですが、
$str = "0xa4a2";
print &hoge($str);
で画面に"あ"と表示させたい場合に、関数&hoge はunpack を使って実現できるとお聞きしたのですが
どのようにすればうまくいくのでしょうか
元々は
1.文字列「0xa4a2」(EUCの「あ」)
↓???
2.文字列「0x82a0」(SJISの「あ」)
↓pack
3.文字列「あ」
※自分のところには、コード(EUC)の形でしか渡してもらえない
という流れで考えていました。1から3に直接飛べるならそれに越したことはないのですが・・・
0725デフォルトの名無しさん
2005/09/06(火) 23:37:18読み込みの方に時間がかかるなら、たしかにファイルへのアクセスが不連続
になって遅くなるかも。
もちろん並列の場合のアルゴリズムは>>714に書いたように一気に読み込むものだけど。
どちらにせよ、速度の差は多分、出ても数倍のオーダーだろうね。
素直に直列(?)処理でよさそうだ。
出力ファイルのドライブを分けるのは、効果ありそうだね。
0726ヽ(´ー`)ノ ◆.ogCuANUcE
2005/09/06(火) 23:42:44元の質問はコレね?
http://pc8.2ch.net/test/read.cgi/tech/1123220967/921
とりあえずロジックを考える時は、やらなきゃいけない事を分けよう。
1. 16進数文字列 → 通常の文字列
2. EUC-JP → Shift_JIS 変換
use Encode qw/from_to/;
# '0xa4a2' → EUC-JP の「あ」
my $str = '0xa4a2';
$str =~ s/^0x//i;
my $euc_a = pack('H*', $str);
# EUC-JP の「あ」 → Shift_JIS の「あ」
from_to(my $sjis_a = $euc_a, 'EUC-JP', 'Shift_JIS');
print $sjis_a;
これでいいかね。
0727デフォルトの名無しさん
2005/09/07(水) 00:04:54$str = pack("n",eval $str);
0728724
2005/09/07(水) 00:06:12できました。ありがとうございます!
需要はないと思いますが、私のミスを整理してみました_| ̄|○
1.pack関数にSJIS「あ」の文字コードを入れてみると、うまく変換された。
2.pack関数にEUC「あ」の文字コードを入れてみると、うまく変換されなかった(実際はコマンドプロンプト上で文字化けしてるだけ)
3.1と2の出来事から、pack関数はSJISしか受け付けてくれないものと勘違い
※pack関数の引数に"SJIS"とか"EUC"が必要なかったため、勘違いしてしまいました。実際は文字コード自動判別してくれるんですね。
4.そして泥沼へ・・・
ご迷惑をお掛けして申し訳ありませんでした。
0729デフォルトの名無しさん
NGNG0730デフォルトの名無しさん
2005/09/07(水) 00:10:37乙。
結果報告は重要だと思うので、しっかりお礼&報告する
姿勢はよいと思うぞ。
0731デフォルトの名無しさん
2005/09/07(水) 00:28:54結果報告だけでいい。
0732デフォルトの名無しさん
2005/09/07(水) 01:46:53ありがと
ところで、binmodeからテキストモードに戻す場合はどうすればいいの?
0733デフォルトの名無しさん
2005/09/07(水) 05:30:01binmode(IN, ":crlf")
0734デフォルトの名無しさん
2005/09/07(水) 05:37:25printf( "%s %s %s\n", splice @data, 0, 3 ) while @data;
じゃね?
0735デフォルトの名無しさん
2005/09/07(水) 09:47:41もし存在しなければ$hogeというファイルを作成→終了。
もし存在したなら$hogeに1を足してまた存在を確認、、、、
とえんえん繰り返していくようにするはどうすればいいですか。
0736デフォルトの名無しさん
2005/09/07(水) 10:17:32「1を足す」の実際の動作やら何やらは特定できんが、
考え方としては
while (1) {
if (-e $hoge) { ++$hoge; }
else { open F, $hoge and last; }
}
0737デフォルトの名無しさん
2005/09/07(水) 10:25:36while (1) {
next if -e $hoge++;
open F, $hoge and last;
}
0738デフォルトの名無しさん
2005/09/07(水) 10:29:06さっそくやってみます。
0739デフォルトの名無しさん
2005/09/07(水) 11:08:30それでも動くけれども、複数同時に走らす場合は、
A: -eでしらべる。なさげ
B: -eでしらべる。なさげ
A: ファイル作成
B: ファイル作成
てなことになりかねないので危険です。
私が書くならsysopenでO_EXCL指定してEEXISTエラーのときだけ
$hoge++してリトライでこんな感じ。
use Fcntl;
my $hoge = 0;
while (!sysopen F, $hoge, O_WRONLY|O_CREAT|O_EXCL) {
$!{EEXIST} or die "sysopen $hoge: $!";
$hoge++;
}
でも一時ファイルですぐ消すんならFile::Tempとか使った方がいい
だろうし、どんどん作られていくなら別にカウンタもった方が効率的
じゃないかと。
0740デフォルトの名無しさん
2005/09/07(水) 11:10:060741デフォルトの名無しさん
2005/09/07(水) 11:15:180742デフォルトの名無しさん
2005/09/07(水) 11:22:46とっとと訊かれたことだけ答えたほうがこの場合よさげ。
0743デフォルトの名無しさん
2005/09/07(水) 12:16:440744デフォルトの名無しさん
2005/09/07(水) 12:44:360745デフォルトの名無しさん
2005/09/07(水) 16:09:11die "Can't change mode.";
0746デフォルトの名無しさん
2005/09/07(水) 16:33:09sourou() if $mi-kosuri-han;
0747デフォルトの名無しさん
2005/09/07(水) 16:43:300748デフォルトの名無しさん
2005/09/07(水) 17:36:12echo $haxahaxa;
0749デフォルトの名無しさん
2005/09/07(水) 18:16:020750デフォルトの名無しさん
2005/09/07(水) 18:33:080751デフォルトの名無しさん
2005/09/07(水) 20:38:44length q caller getc and print chr ord qw q do q and print chr ord q local and print chr ord qw q uc q and print chr ord q tie gt
0752デフォルトの名無しさん
2005/09/07(水) 20:48:400753デフォルトの名無しさん
2005/09/07(水) 20:56:420754デフォルトの名無しさん
2005/09/07(水) 21:14:46オススメ。
■ このスレッドは過去ログ倉庫に格納されています