Perlコーディング初心者質問スレ Part 54

このエントリーをはてなブックマークに追加
1nobodyさん
Perlのコーディングで困ってる人のスレです。

【投稿する際の注意】
質問するときは内容をよく吟味してから投稿してください。
「コマンドの意味がわかんない」とかはマニュアル見ましょう。
回答者さんは何でも屋じゃありません。

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

最低でも1と3が無いと誰も答えられないよ。
ソース貼る時は、全角スペースでインデント忘れずに。
良い回答は良い質問から。一緒に勉強しましょう。

お勧めサイトは >>2-10

前スレ http://pc10.2ch.net/test/read.cgi/php/1164519503/
過去ログ倉庫 ttp://user.ftth100.com/mirrorhenkan/perl/
2nobodyさん:2007/02/10(土) 19:23:04 ID:???
ム板Perlスレより 1 of 2

[プログラミング自体の経験が無い奴はまずココを読め]
Perlプログラミング講座: ttp://www.site-cooler.com/kwl/perl/

[本]
リャマ: ttp://www.oreilly.co.jp/books/4873111269/
駱駝: ttp://www.oreilly.co.jp/books/4873110963/
Effective Perl: ttp://www.ascii.co.jp/books/detail/4-7561/4-7561-3057-7.html
クックブック: ttp://www.oreilly.co.jp/books/4873112028/

[オンラインマニュアル] (追加)
最新のドキュメント: ttp://search.cpan.org/dist/perl-5.8.8/
perl5.8.xのドキュメント(一部): ttp://www.kt.rim.or.jp/~kbk/perl-5.8/
perl5.005_03 のドキュメント: ttp://www.kt.rim.or.jp/~kbk/perl5.005/
日本語ドキュメント検索: ttp://www.cpan.jp/search.cgi
perldoc.jp: ttp://www.perldoc.jp/
Perldoc.com: ttp://www.perldoc.com/
3nobodyさん:2007/02/10(土) 19:23:37 ID:???
4nobodyさん:2007/02/10(土) 19:25:07 ID:???
関連スレ
CGI: Common Gateway Interface part 13
http://pc8.2ch.net/test/read.cgi/php/1126436361/

【Perl,CGI】参考書籍 第三版
http://pc8.2ch.net/test/read.cgi/php/1030209573/

【Perl】ファイルロック(排他処理)について語ろう
http://pc8.2ch.net/test/read.cgi/php/1024795138/

★負荷軽減対策委員会(Perl、PHP)★
http://pc8.2ch.net/test/read.cgi/php/1034645635/

CGIに依存しないPerlの話題一般/Part2
http://pc8.2ch.net/test/read.cgi/php/1030548610/

★三 【 スクリプト改造工房 PART 9 】 ★三
http://pc8.2ch.net/test/read.cgi/php/1143834740/

【 スクリプト改造依頼スレ 】(丸投げ) part6
http://pc10.2ch.net/test/read.cgi/php/1157787046/
5あぼーん:あぼーん
あぼーん
6あぼーん:あぼーん
あぼーん
7nobodyさん:2007/02/11(日) 03:49:47 ID:???
>>1
8nobodyさん:2007/02/11(日) 11:40:00 ID:R1v+g7+l
>>5, >>6
9nobodyさん:2007/02/11(日) 11:51:13 ID:uXIy6Xmt
perlで浮動小数点を 10のn乗 する計算をしたいのですが、ズレというのは発生するのでしょうか?


0.57 * 100
0.07 * 100

IE6のJavaScriptだと上の場合 56.99999 となりズレます。
いろんな数値をperlで試しており、今のところズレは起きていないのですが perl は大丈夫なのでしょうか?
10nobodyさん:2007/02/11(日) 12:07:58 ID:uXIy6Xmt
すいません。追記です。
以下のようにすると 57, 56 と結果が返されます。
---------------------------------
print 0.57 * 100;
print int(0.57 * 100);
---------------------------------
0.57 * 100 の結果は "57" に見えるけど本当は違うのでしょうか?
11脱帽:2007/02/11(日) 12:50:44 ID:???
心配ならbignum.pmでも使えば。
12nobodyさん:2007/02/11(日) 14:24:00 ID:???
0.57 → 57 / 100
0.57 * 100 → 57 * 100 / 100
13nobodyさん:2007/02/11(日) 16:04:38 ID:uXIy6Xmt
>>11
有難うございます。bignum.pmというのは知らなかったです。
Math::BigFloat をよく使うのですが、大量の計算をする場合にはスピードがだいぶ気になります。
10や100などの計算だけでも..と思ったのですが。

>>12
すいません。私には何が言いたいのか理解できません(>_<)
もう少し教えて頂け無いでしょうか。
14nobodyさん:2007/02/11(日) 16:06:28 ID:???
C使った方がええんちゃう?
15nobodyさん:2007/02/11(日) 18:39:39 ID:???
print int(sprintf('%f',0.57 * 100));
16nobodyさん:2007/02/11(日) 22:17:14 ID:???
前スレ埋めろよ
17 ◆TWARamEjuA :2007/02/11(日) 23:57:13 ID:??? BE:1742382-BRZ(6761)
いつの時代の人間だよ(嬉)>>埋め推奨
放置すればよろし。
18nobodyさん:2007/02/12(月) 02:02:34 ID:???
ヌル文字を含んだ値をPOSTで送って、受け取った先でReadParseした場合、値からヌル文字は削除されてしまうんですか?
19nobodyさん:2007/02/12(月) 02:52:50 ID:???
20nobodyさん:2007/02/12(月) 14:57:27 ID:EeKO4sif
CGI_Liteモジュールを使って配列を取得することはできますか?

<INPUT TYPE="text" NAME="data" VALUE="a">
<INPUT TYPE="text" NAME="data" VALUE="b">
<INPUT TYPE="text" NAME="data" VALUE="c">
のようなフォーム内のデータを
@formdata = ('a','b','c');
というように取得したいんですが、

%form = $cgi->parse_form_data();
@formdata = $form{'data'};

だと取得できませんでした。
そもそも配列をそのまま取得することはできないんでしょうか?
情報が載っているサイトだけでも良いのでアドバイスお願いします。
21nobodyさん:2007/02/12(月) 15:17:31 ID:???
CGI_Lite.pmは使ったことないんだけど $formdata = $form{'data'}; というオチは無い?
2220:2007/02/12(月) 15:27:01 ID:???
>>21
レスありがとうございます。

そういうオチはないです。
$formdata = $form{'data'}
にしても
@formdata = $form{'data'}
にしてもも同じ値(リファレンス?)が1つだけ返ってくるだけです。
ちなみに
$formdata = split(/ /,$form{'data'});
とかもやってみましたが、こちらは何も返ってきませんでした(当然ですが)。
23nobodyさん:2007/02/12(月) 17:09:55 ID:???
>>20-22
> 同じ値(リファレンス?)が1つだけ返ってくるだけです。
そこまで分かってて何故デリファレンスしないんだ。
http://www.kt.rim.or.jp/~kbk/perl5.005/perlref.html

@formdata = @{ $form{'data'} };
2421:2007/02/12(月) 17:29:44 ID:???
>23
俺を含めないでくれ。
2520:2007/02/12(月) 20:57:49 ID:???
>>23
あ・・・。お恥ずかしい。
その通りですね。
自分なりにデリファレンスやってみたつもりが
全然違う書き方してたみたいです。
デリファレンスの書き方で混乱しないように勉強します。
ありがとうございました!
26nobodyさん:2007/02/13(火) 15:50:27 ID:Kq8fojs+
""(はしごたか)などの文字をperlのスクリプトでPostgreSQLに保存する方法を教えていただけないでしょうか?
perlもPostgreSQLの文字コードもEUCで保存しています。
どのように文字をエスケープすればいいのか検索して調べてもわかりません。
よろしくお願いいたします。
27nobodyさん:2007/02/13(火) 16:14:50 ID:???
Jcode::CP932
2826:2007/02/13(火) 18:34:04 ID:Kq8fojs+
>>27
よろしければもう少し詳しくお願いできないでしょうか?
29nobodyさん:2007/02/13(火) 19:14:11 ID:???
どこで不具合が出てるのかわからない
処理中に文字化けしているのか、出力時に文字化けしているのか
そもそも文字化けなのか?DBに入らないのか?

文字化けならJcode::CP932(ただし要Jcode.pm上書き)か
WebだけならEncode::XMLCREFがいいんじゃないかと思いました
30nobodyさん:2007/02/13(火) 21:14:34 ID:???
教えていただけないでしょうか。
BBQ規制に関してです。
BBQ規制に巻き込まれた人を規制からはずすということをしたいのですが、
そのために
"allowhost.txt"に書き込まれたホストを一行ずつ読み込んで一致すれば規制を抜ける
ということにしたいです。
以下のソースの書き方では
串を入れるとBBQ規制には引っかかるのですが、
同じ串を"allowhost.txt"に書き込んでも規制を抜けません・・・。
どういう描き方が適当なんでしょうか?
31nobodyさん:2007/02/13(火) 21:17:02 ID:???
ソース。汚い書き方ですいません・・・。
sub checkProxyList {

 ###ホスト取得###
 $RADDR = $ENV{'REMOTE_ADDR'};
 $host = $ENV{'REMOTE_HOST'};
 $addr = $ENV{'REMOTE_ADDR'};
 if ($host eq "" || $host eq "$addr") {
  $host = gethostbyaddr(pack("C*", split(/\./, $addr)), 2);
 }
 if ($host eq "") { $host = $addr; }

 ### $hostが"allohost.txt"と一致しているか調べる###
 open(ALLOWHOST,"allohost.txt");
 @allowhost = <ALLOWHOST>;
 close(ALLOWHOST);
  foreach $allowhost (@allowhost) {
   $allowhost =~ s/\r//;
   $allowhost =~ s/\n//;
   $search = index($host, $allowhost);
   if($search >= 0){
    $flag = 1;
   }
  }
32nobodyさん:2007/02/13(火) 21:17:27 ID:???
続き

 ###BBQ規制###
 $RADDR =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
 $query_addr = "$4.$3.$2.$1.niku.2ch.net";
 $address = join('.', unpack('C*', gethostbyname($query_addr)));
 if ($address eq '127.0.0.2'){
  if($flag == 1){
   print "Content-Type: text/html\n\n";
   print "規制を抜けました";
   exit;
  }
  else{
   print "Content-Type: text/html\n\n";
   print "公開Rroxyからの投稿は受け付けていません!";
   exit;
  }
 }
 $flag = 0;
 return 0;
}
33 ◆TWARamEjuA :2007/02/13(火) 21:31:01 ID:??? BE:1307726-2BP(6811)
use Net::DNS;

my $Resolve = Net::DNS::Resolver->new(
udp_timeout => 30, # お好きな時間(タイムアウト)に♪
);

# --- BBQ・・・
my $BBQ_Status;
my $query = $Resolve->search(sprintf qq|%s.niku.2ch.net.|, join '.', reverse split( /\./, $IP_Address));
if ($query) {
 foreach my $rr ($query->answer){
  next unless $rr->type eq "A";
  $BBQ_Status = $rr->address;
  last;
 }
}

print qq|-- BBQ --\n|;
printf qq|\t$IP_Address -> %s\n|, $BBQ_Status
  ? "Roasted(-_-)"
  : 'None(^-^)';

風呂敷確認君より抜粋♪
34nobodyさん:2007/02/13(火) 22:48:50 ID:???
>>33
早速の返答どうもありがとうございます。
>>31-32のソースではなぜBBQ規制から抜けないのでしょうか?
35 ◆TWARamEjuA :2007/02/13(火) 23:07:28 ID:??? BE:1742944-2BP(6811)
>>34
ほへ?
エスパーさんぢゃないのでよくわかんないけれども、exit;しているからヂャネ?
36nobodyさん:2007/02/13(火) 23:11:09 ID:???
return $flag;
にしないと、なんの為にフラグ用意してるのやら
3726:2007/02/14(水) 11:57:59 ID:mjFZ4k3U
>>29
""などの文字をDBに入れようとすると、DBからのエラーが帰ってくるんです。
Webminから直接DBのデータを操作して""を入れるとすんなりと入るので、
perlで入れるときは文字に何らかの処理をかける必要があるのかと思ったのですが。
入力するデータはCSVファイルで、jcode.plを使ってSJIS→EUCへエンコード後に、SQLコマンドを実行してDBに書き込んでいます。
""などの文字が入っていなければ、エラーはないのですが、入っているとエラーが帰ってきてDBへの書き込みができません。
スクリプトの文字コードはEUCで、perlのバージョンが5.6.1なのです。
38nobodyさん:2007/02/14(水) 12:35:03 ID:???
エラーメッセージがあるなら書けよ
39nobodyさん:2007/02/14(水) 12:39:29 ID:???
とりあえずwebminから入れたのをperlから読み出したときのバイト列と
書き込もうとしてうまくいかないバイト列を比較してみてはどうか。
君の変換がおかしいのか、もっと先に問題があるのかの切り分けにはなる。
40nobodyさん:2007/02/14(水) 14:04:28 ID:???
そもそも という字は、euc-jp で表現できるのか?
41nobodyさん:2007/02/14(水) 14:27:20 ID:???
(はしごだか)はeuc-jpでも表現できるみたい。>39が言ってるけど、まず切り分けることだね。

# そもそもeuc-jpをやめて全部utf-8に…ゲフンゲフン
4240:2007/02/14(水) 14:41:35 ID:???
> (はしごだか)はeuc-jpでも表現できるみたい。

すまんこ。euc-jp で表現できることを確認しますた。
43nobodyさん:2007/02/14(水) 14:49:15 ID:???
>>40
はしごだかはIBM拡張文字なのでなんらかの拡張が必要なんじゃない?
拡張したのもeucと呼ぶ人がいるけれども、拡張の方法も一通りでは
ないからどれのつもりで言ってるか気をつけないといけない。

ttp://msyk.at.webry.info/200511/article_2.html あたり参照。

5.6はいい加減捨てて5.8.x+Encode::EUCJPMSを使う方がいいん
じゃないかと思う。
44nobodyさん:2007/02/14(水) 14:55:18 ID:RW6nNThJ
http://www.youtube.com/watch?v=KyLqUf4cdwc

perlって難しすぎる。
4540:2007/02/14(水) 15:07:46 ID:???
あー、なんか読めないすね。

秀丸で、「高 」を euc で保存 (euc.txt)
秀丸で同ファイルを開くと、ちゃんと読める

$ hexdump -C euc.txt
00000000 b9 e2 20 fc e2

以下は、utf-8 な fc6 に ssh して実行。

$ iconv --from euc-jp --to utf-8 euc.txt
高 iconv: 位置 3 で不正な入力シーケンスがありました

$ cat euc.txt | perl -MEncode -ne 'print decode("euc-jp", $_);'
Wide character in print at -e line 1, <> line 1.
高 ?
46nobodyさん:2007/02/14(水) 15:33:57 ID:???
>>45
euc-jp-msでは?
47nobodyさん:2007/02/15(木) 00:36:29 ID:???
自分のサイトにチャットを置いていて、携帯電話からも利用できるようにしたところ
どうにも困った事がおきたので質問させてもらいます。

チャットには参加者一覧が表示されます。携帯からチャットにアクセスすると、その
参加者一覧に自分の名前がいくつも表示されるという不具合が起きました。ログを見る
と携帯電話は数分でIPが変わっていて、それをスクリプトが別端末からのアクセスだ
と誤認したのが原因でした。(最終アクセスから5分経つとそのIPの参加者の名前はリ
ストから削除します。)

そういえば2chは携帯で書き込んでも毎回同じIDだなと思い、何度かfusianasan
をしてみるとIPは(たぶん)変わっているにも関わらず、全て"07012360463529_vi"とい
う謎の文字列が出てきました。2chは同一端末からのアクセスをなにかエロい事をして
認識しているらしいです。

参加者リストに同じ名前が複数あるときは一つにまとめようかと考えていますが根本
的には解決していないので、気持ち悪いので、何かいい案を下さい。

# KENT WEBのCOMCHATをベースに改造してつかっています。
# ttp://www.kent-web.com/chat/comchat.html
48nobodyさん:2007/02/15(木) 00:40:35 ID:???
mod_perl使うために、グローバル変数をどうしたらいいのか
教えていただきたいのですが、よろしくお願いします。

use strict;
use warnings;
use CGI::Carp qw/fatalsToBrowser/;
この3行をソースコードのはじめのあたりに加えると
Global symbol "$xxxx" requires explicit package name at ・・・
こういうエラーが出てきました。

・グローバル変数の探し方は、この方法で大丈夫でしょうか?

・この出てきたグローバル変数の中で、”値の変化しないグローバル変数はそのまま”
”値の変化するグローバル変数にmyを付けて”、動作も矛盾しないようなコードに
直せばよいのでしょうか?
マルチスレッドのようなイメージで考えればよいでしょうか。
49nobodyさん:2007/02/15(木) 01:03:55 ID:???
use vars qw(%xxxx);
50nobodyさん:2007/02/15(木) 01:28:23 ID:KpCoXSAW
>>47
セッションID(の類)をリロードの時に送信するとか。
リロード方法によってはIDの伝達途切れるから、
名前+UAくらいで判別するのも悪くはないと思う。
2chが何やってるかは知らない

>>48
他言語の経験あるならその方針で大丈夫
51nobodyさん:2007/02/15(木) 02:02:42 ID:???
Perl+CGIをやってみようかと思い勃ったが仏滅、どうしようもなくハマってます。
助けてやってください。

さくらのシェルで、viでこんなのを書きました。

 #!/usr/bin/perl
 print "Hello World!\n";

そしてchmod 755して、ブラウザからhttp://foo.jp/var.cgiとやったらサーバエラーになるんです。orz
私は何か根本的な事を知らないのでしょーか?

52nobodyさん:2007/02/15(木) 02:11:09 ID:???
CGIのべんきょーを他のユーザーを巻き込む可能性のあるサーバーでやったらあかんでしょ。

ActivePerlと04WebServerでもダウンロードしてローカルでやんなさい。
53nobodyさん:2007/02/15(木) 02:17:23 ID:???
>>50
プログラミング勉強始めて一ヶ月なので。(汗
レスありがとうございます。助かりました。
54nobodyさん:2007/02/15(木) 02:34:06 ID:???
>>53
助かったの?
CGIの場合少なくとも最初に
print "content-type: text/html\n\n";なり、
print "content-type: text/plain\n\n";なりの出力が必要。
確かに根本的な事。
ローカルの方が作業もしやすいよ。
55nobodyさん:2007/02/15(木) 02:50:34 ID:???
>>54
動きますた!
そんな類のこったろうと思いましたが、具体的に何書いて良いかがわかりませんでした。(^^;
これでまっとうな勉強が出来そうです。

>>52
いやーローカルの鯖でシェルからperl ./var.cgiしたら文句なく動いてるのに、cgiとして動かしたら何故動かない!とテンパってたんです。(^^;
生のperlとCGI経由の違いが解ってようやく前に進めそうです。

56nobodyさん:2007/02/15(木) 06:55:48 ID:???
> ActivePerlと04WebServerでもダウンロードしてローカルでやんなさい。

VMware server と、適当な Linux でいいんじゃないの?
5753:2007/02/15(木) 08:12:01 ID:???
53です。
SpeedyCGIなんとか入れてみました。ネットで調べたところ、
「使用し終わったグローバル変数がそのまま再利用されるため、
変数にゴミが入った状態になります。 グローバル変数の初期化が前提です。」
とありました。

i=0; i++; i++; i++; i++; i++; print("i");
i=0;と初期化して、5回足しています。

1,2,3,4,5と順調に加算されて、printする瞬間iを参照したら、
5でなくi=3だったということには、ならないのでしょうか。

使用し終わったグローバル変数がそのまま再利用
ということなので、ひとつのプロセスが使用中のグローバル変数は、
他のプロセスで再利用(参照)されないで、新しいプロセスは新しいグローバル変数が
割り当てられるんでしょうか。(わかりづらくてすみません)

初期化するだけで大丈夫、という仕組みが難しいです。
解説しているページやアドバイスなどお願いします。
58nobodyさん:2007/02/15(木) 09:07:33 ID:???
>>47
それはEZ番号ではないですか。auでEZ番号を通知するモードにしていると、公式サイトでなくても
環境変数$ENV{HTTP_X_UP_SUBNO}から取得できます。端末の同定には都合がいいですが、
他のキャリアでは通用しないと思います。やはり、最初のアクセスの時にセッションIDを発行して
引き回すしかないのでは?
59nobodyさん:2007/02/15(木) 10:55:43 ID:???
携帯でセッション引き回してるのにセッション切れが多発して
おっかしいなーとおもったらIPマッチ使ってた
60nobodyさん:2007/02/15(木) 11:25:12 ID:???
>>47
携帯は固有番号をもっている。2chはそれを取得している。IPアドレスはリクエスト毎に可変で、しかも1ページの取得に複数のIPを使うこともある。
固有番号は、(たしかEzWeb以外は)ユーザが許可したらHTTPヘッダに埋め込まれ、仕様は各ベンダーサイトで見れる。
>>57
#!〜から始まる1行目(名前を忘れた)に変数を初期化するオプションがあったはず
61nobodyさん:2007/02/15(木) 14:47:43 ID:???
>>47
auのケータイは常に EZ番号 (旧サブスクライバID) という個体識別番号を送信している。
Softbank もデフォで全てのサイトに送信されると思った。

DoCoMoは確か投稿時に確認画面がでて、(,,゚Д゚)∩ハイッ!! を押すと個体識別番号が送信される。

携帯から fusianasan を安易にやることは避けたほうがいいし、
Webアクセスもなるべく自宅に設置したGWなどを使うか、全てのサイトで個人情報を入力しないほうがいい。

これは解約まで基本的に不変な情報であり、極めて危険。
ショッピングサイトの情報が漏洩したら、ワンクリサイトにアクセスしただけで、ワンクリ業者が住所などの個人情報を入手できることになるから。



6247:2007/02/15(木) 21:15:09 ID:???
みなさんレスありがとうございました。
固有番号を使うのはいろいろ面倒だったのでセッションIDを実装することにしました。
6353:2007/02/15(木) 23:45:03 ID:???
>>60
レスありがとうございます。
マルチスレッドみたいに、ひとつのグローバル変数を参照している
わけではないんですね。はじめだけ初期化すれば、あとは他のプロセスから
影響ないんですね。ふむふむ。
>#!〜から始まる1行目
さっそく調べてみます。ありがとうございました。
64nobodyさん:2007/02/16(金) 00:11:07 ID:???
申し訳ありませんが、教えてください。

【質問の概要】
Perlスクリプトを記述する際の文字コード種類をUTF-8とした場合の、文字置換の考え方に対する質問です。

【質問の内容】
下記のソースを書いたとします。
#------------------
$char = "aBc";

$char =~ s/a/a/g;

print $char;
#------------------

上記ソースをShift-JISで記述した場合、全角の"B"の文字コードは"8261"のため、半角の"a"の文字コード"61"で2バイト目が置換されてしまい、文字化けしてしまいます。

これと同一のソースをUTF-8で記述すると、半角の"a"が、全角の"a"に置換されます。

この結果を見る限り、UTF-8でソース記述すると、文字置換の際に、1バイト、2バイト目の誤置換を意識しなくてもいいように思うのですが、この認識は間違っているでしょうか?

もし、認識違いの場合は、UTF-8の場合、どのような文字の並びで誤置換が起こるのか、教えていただけると幸いです。

申し訳ありませんが、ご教授ください。
65nobodyさん:2007/02/16(金) 00:55:50 ID:MoploLOU
お願いがあります。

Perl で、以下のCGIを作りました。
1)CSVファイルをアップロード
2)アップロードしたファイルを処理
3)処理したファイルのリンクを表示してダウンロード。

ところが、2)が重くて待たされるので、(MAX数分)
プログレスバーを表示しようと思うのですが、
どうやったらいいか・・・・。

ちゃちゃっと簡単にできる方法があればよろしくお願いします。m(_ _)m
66nobodyさん:2007/02/16(金) 01:28:03 ID:???
>>65
その数分もかかるへっぽこな処理を100倍高速化する。
67nobodyさん:2007/02/16(金) 01:41:11 ID:???
>>64
その結果を見ただけで意識しなくてもいいと判断する事は出来ないが、
正しいUTF-8ではそのような問題や、EUC-JPで良く発生するような
ずれてマッチする問題は起こらないことが保証されている。
参考資料: RFC2279(obsoleteだがUCS-4の範囲を全て表現できるため), RFC3629

というのもUTF-8というエンコーディングは面白い構造をしている。
まずASCIIの範囲はそのままASCIIのために割り当てられていて、
マルチオクテット文字には出現しない。これはEUC-JPと同じ。
で、問題のマルチオクテット文字の表現なのだけれど、
nオクテットで表現されるUTF-8文字は、最上位ビットから
nビット1が連続した後に0が来るようになっている。
全ての非ASCIIのUTF-8文字は2byte以上で表現されるので、
これは1オクテット目が10xxxxxxにならないということ。
そして、2オクテット目以降は上位2ビットが必ず10になっている。

これらによって、マルチオクテット文字中にASCII文字が登場したり、
他のUTF-8文字にずれてマッチするようなことがないことが保証できるわけだ。

さて、ここまではUTF-8に対する一般的な話だが、実はPerl(5.8以降、5.6は怪しい)は
UTF-8を内部エンコーディングとして正式にサポートしている。
文字列にはUTF-8フラグというものが用意されており、
マルチオクテット文字を1文字として扱うことが出来るようになっている。
この辺の話はテンプレ>>3の[Perl5.8Unicodeメモ]にあるサイトが詳しいので、
必要ならとりあえずそっちを読んでくれ。
68nobodyさん:2007/02/16(金) 01:53:09 ID:???
>>67
まるごとPerlの記事もおすすめ
69nobodyさん:2007/02/16(金) 01:55:50 ID:???
間違えた>>64
70nobodyさん:2007/02/16(金) 06:38:18 ID:MoploLOU
>>66
数倍ならば高速化できますが、100倍はムリだとおもいます。

処理内容は以下に記載。
 1)CSVを1行を読み込み。
 2)対応するWEBページのURLを作成。
 3)上記URLをもとにWEBページをダウンロード。
 4)ダウンロードした情報をCSVに付加。

 処理時間は 1行あたり凡そ1秒。

既にダウンロードした情報はDBにキャッシュしていますが、
情報量の関係で
「新規にWEBページをダウンロードしなければならない」場合が
発生するのです。
71nobodyさん:2007/02/16(金) 09:57:57 ID:???
プログレスバー表示はクライアントサイドの話だから、板違いかな。
例えば、AjaxとかCommetとかFlashで何秒おきかに進捗状態を取得して表示するとか。
かなり面倒なことは確か。
72nobodyさん:2007/02/16(金) 10:28:08 ID:???
子プロセス?
73nobodyさん:2007/02/16(金) 14:30:20 ID:???
フラグ立てちゃうとエラーが…
7464:2007/02/16(金) 19:29:33 ID:???
>>67-68
丁寧な説明ありがとうございました。
>その結果を見ただけで意識しなくてもいいと判断する事は出来ないが、
その通りですね、すみません・・・
7565:2007/02/16(金) 23:38:29 ID:MoploLOU
>>71
どうもです。
やはり ajax ですか・・・、調べてみます。
76nobodyさん:2007/02/17(土) 01:22:16 ID:???
>>75
使ったことないけど、シンプルな進捗表示でいいなら
multipart/x-mixed-replace でさくっとできそうな気がする
7776:2007/02/17(土) 01:32:05 ID:???
なんかIEで使えないとか書いてあったな…。
やったことある方法では「<script> statusbox.value = "現在5件処理完了"; </script>」
的な1行javascriptをautoflushでprint。
78nobodyさん:2007/02/17(土) 17:26:59 ID:???
>>70
そんな事、CGIでやるべきではないと気付け。
79nobodyさん:2007/02/17(土) 20:47:43 ID:???
ファイルの中身を配列に入れたいんですけど、
my @file = <FILE>;
これより効率の良い方法ありますか。
ファイルの中身は最大で100KBです。
共有鯖なので心配で使えません。
80nobodyさん:2007/02/17(土) 21:23:25 ID:???
は?
81nobodyさん:2007/02/17(土) 21:33:47 ID:???
>>79
最終的に何がしたいのか、および何の効率かによる。

メモリ効率を気にしていて、「ファイルの中身を」丸ごと「配列に入れたい」のなら、
その方法だとデータサイズの2倍程度メモリを消費して、
1行ずつpushで代入する方法だとデータサイズと同じ程度だったが。
(perl5.8.7 on FreeBSD5.4調べ)

本当にやりたい事を考えずに配列に代入する効率だけ考えるのは本末転倒というものだ。
82nobodyさん:2007/02/17(土) 21:44:02 ID:???
readして改行コードでsplit
83nobodyさん:2007/02/17(土) 21:55:29 ID:???
>>81
(ファイルのフォーマットは先頭が数字で固定)
my @log = <FILE>;
my($start,$end) = hoge(); #ユーザーの入力による数字
my $new = ( $log[$#log] =~ /^\d+/s ) ? $& : 0;
my $old = ( $log[0] =~ /^\d+/s ) ? $& : 0;
$start = $old if( $old > $start );
$start = $new if( $start > $new );
$end = $old if( $old > $end );
$end = $ned if( $end > $new );
$end = $start if( $start > $end );
my @choice = print_request_lines(\@log,$start,$end);
sub print_request_lines {
  my($log,$start,$end) = @_;
  my $count = $start;
  $end = $count unless($end);
  foreach ( @$log ) {
    if ( /^\Q$count\E/s ) {
      print;
      if ( $count >= $end ) {
        last;
      }
      else {
        $count++;
      }
    }
  }
}
あとあとはこんな処理です。長いので一応簡潔にまとめたつもりです。
read(FILE,my $hoge,-s FILE);とか?
気になるのは鯖の負荷です。一日2万弱アクセスあります。
8481:2007/02/17(土) 22:00:24 ID:???
... $ned if....
my @choice = ...
あたりはまとめミスですorz
85nobodyさん:2007/02/17(土) 22:02:22 ID:???
そして名前ミス('A`)
83でした。すみません
86nobodyさん:2007/02/17(土) 22:28:50 ID:???
>>83
指定される範囲は通常データ全体に比べて非常に小さいものかな?

番号がソートされて並んでいるなら二分探索が有効。O(log n)に出来る。
行頭探すのがちょっと面倒だがなー。データ構造を変えることが可能ならば、
あらかじめ番号に対してオフセットを記録しておくような簡単なindex付けを行っておくのが吉。
87nobodyさん:2007/02/17(土) 23:07:21 ID:???
>>86
指定される範囲は予想ではデータ量の2割りくらいがメインです。
10割りの時もありますが。

二分探索を調べて見ましたが使いまわしできなくなりそうなのでやめました。

結局ファイルを小刻みに分割することにしました。
index付けとは言えませんが、
先に位置情報ファイルを読み込んで該当ファイルを探すといった感じです。

>>81 >>86 大変勉強になりました。ありがとうございました。
88nobodyさん:2007/02/18(日) 04:57:02 ID:???
>>83
行頭についてる整数値を取得すれば1行読みの1パスで行けるんじゃない?

>if ( /^\Q$count\E/s ) {
の行、$count=10のとき行頭が"100"でもマッチするね
データ構造上無いのかも知れないけど

ちなみに小分けしたファイルのどれから読み込むのかを
要求された値から機械的に算出できるようにするという工夫もあるよ
89nobodyさん:2007/02/18(日) 09:12:59 ID:???
>>83
>1行読みの1パス
ファイルが100KBを超えるたびに先頭の1行を削除していたので
$new,$oldをどうやって取得するかが問題でした。

>if ( /^\Q$count\E/s ) {
if ( ^\Q$count\t\E/s )にしました。

>機械的に算出
(ファイルを100件刻みで小分け)
my $file = './log/*.dat';
my $fle_numbe = int($start / 100) + 1; #+1は必ずtrueにする為
$file =~ /\*/$file_number/e;

とりあえずこんな感じにしました。
ファイルをまたぐ方法を考え中です。
なんとなくpipeを勉強(`・ω・´)
9065:2007/02/18(日) 17:02:29 ID:qiEEvOwU
>>78
>そんな事、CGIでやるべきではないと気付け。

 CSV処理サービスを多数に公開する趣旨にもとづき、CGIで試作しています。
 CGI以外で、多数のユーザーに処理サービスを公開する方法がありましたならば、
 ご教授願います。
91nobodyさん:2007/02/18(日) 17:24:45 ID:???
CGIでも場合によってはアリだと思うよ。

簡単な方法としては、
(1) HTTP response header を返す。
(2) HTTP body の先頭を返す。
ここで総処理件数を表示しても良い。
(3) 時間の掛かる処理を開始する。
(4) 1件処理毎に何らかのデータを返す。
(プログレスバーのような格好の良い物の代替として)
(5) できあがったCSVをダウンロードするためのリンクを出力。

つまり、プログレスバーの代わりに、(4) で何らかのデータを
返すだけだけどね。
垂れ流し的に「n件目、処理中」ってのが同じページに繰り返し
出ちゃったり、ちょっとかっこわるいけど。
92nobodyさん:2007/02/18(日) 17:34:02 ID:???
もうちょっと手の込んだ方法。

時間の掛かる処理を開始する前に

<meta http-equiv="Refresh" content="10;URL=hoge.cgi?jobid=123">

みたいなページを返して、定期的に hoge.cgi を呼び出させる。
上記のページをクライアント側へ返したらSTDOUTとSTDERRはcloseする。

hoge.cgi は与えられたパラメータ(例示のjobid=123みたいな)でどの処理か
特定し、処理途中なら進捗具合を返す、の繰り返し。

処理完了なら、CSVダウンロードのためのリンクを返す。

で、どうだろ。
93nobodyさん:2007/02/18(日) 17:58:06 ID:???
ローディングとかのアニメGIFでも表示させてろよ
十分だろ
94nobodyさん:2007/02/18(日) 18:05:14 ID:???
>>93
割り切って人間に対してはそれでも良いかもね。

しかしHTTP通信上、一定時間データが流れないと、ブラウザ側が
エラーと見なしてしまうことがあるからね。
9565:2007/02/18(日) 20:30:00 ID:qiEEvOwU
>>91, >>92
CGI の神のご教授、感謝です。
いままでは local 環境でのプログラミング( kernel層)ばかりだったので、
CGI は可也勝手が違います。
96nobodyさん:2007/02/19(月) 05:29:32 ID:???
初心者の浅知恵でしかないんだけど、処理中に一定数ループしたら、
ちょっとだけファイル書き出しておけばよさそうに感じるけど、そういう感じって出来ないのかね。
処理してるのと別の工程でそのファイル読み出して進展状況とするみたいな感じで。
97nobodyさん:2007/02/19(月) 07:55:57 ID:vpFQD8kw
>>96
できるよ。一度ユーザに画面遷移してもらうという点では>>92と同じ考え方。
実装では>>92もファイルを書き出すことになるだろうけど。
98nobodyさん:2007/02/20(火) 02:04:21 ID:???
話の流れをぶったぎってすいませんが質問です。
use CGI;
$q = new CGI;

foreach($q->param){
といった形のソースで、POSTされたデータをハッシュで受けたいのですが、keyにあたる部分にHTMLでいうところのID要素を与えたいと思います。
ループ内でVALUEは$_で受け取れますが、ID要素に当たる部分を取得する方法はありませんか?
99nobodyさん:2007/02/20(火) 08:31:07 ID:???
>>98
http://perldoc.jp/docs/modules/CGI.pm-2.89/CGI.pod
「スクリプトの渡された全てのパラメータの名前の取り出し」から
「パラメータリストのハッシュでの取り出し」まで読もうな。
100nobodyさん:2007/02/20(火) 10:28:24 ID:???
>>98
不可能。ID属性に関する情報はブラウザから飛んでこない。