【Perl】初心者コーナーPart10
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
02/02/24 22:18ID:zOj6Yq/31:自分はこう言う事がしたい。
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を見よう。
0384nobodyさん
02/03/10 16:58ID:???use Jcode; して、20行目を
print length (jcode($_->[0])->utf8);
にしてみるとどう?
0385370
02/03/10 17:07ID:???->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.
0386384
02/03/10 17:23ID:???utf8なやつだと解釈しようとして失敗してる(eucなんだから当然)からなわけで。
だからlengthに渡すものをutf8に変換しておこう、と言う改造をしてみたんだが。
納得いかないならこんなのとか。
{
no utf8;
$\ ="\n";
while ($_ = ....){
print length($_->[0]);
}
}
0387384
02/03/10 17:34ID:???なんか勘違いした事書いたかも。スマソ。
0388370
02/03/10 17:41ID:???申し訳ない、>>384が目に入ってませんでした。
それでOKです!
いろいろ試した結果、eval qq{"$_->[0]"}でも正常化できるみたいです。
でもno utf8じゃダメっぽいです…。
とりあえず、解決たので一安心です。
どうもありがとうございました。
0389nobodyさん
02/03/11 01:26ID:???今さらでスマンが、
keysやvaluesでいくと%HASHが巨大だった場合に危険じゃない?
どうせやるなら
++$num while (my ($key, $value) = each %HASH);
とか?めんどくさいけど。
0390nobodyさん
02/03/11 01:56ID:???代入はいらないのじゃない?
0391nobodyさん
02/03/11 02:00ID:???スカラコンテキストで使うとそれぞれの数を返すっていう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:ILIPqmP1while文で只管ぐるぐる回して
5秒ぐらいで処理を抜けるような感じにしています。
でも、なんかもっとちゃんとした方法があると思うんですがどんな方法があるんでしょうか?。
0395393
02/03/11 14:17ID:???やはりこういうものがあったんですね(^^
ありがとうございました。
もっと勉強してきます・・・
0396nobodyさん
02/03/11 18:53ID:???コレを見てくれ!
0397nobodyさん
02/03/12 02:51ID:???スクリプトがわからないのでお教えいただけませんでしょうか?
または参考URLをお願いします。
0398nobodyさん
02/03/12 02:56ID:???0399sage
02/03/12 03:05ID:XpAJ+W0c0401nobodyさん
02/03/12 03:31ID:???基本はこれだけど, Perl5からは srandで種作らなくても自動で最適な種が作られるようになってる。
srand time;
print rand 100;
0403nobodyさん
02/03/12 04:52ID:52qV3w5qシステム公開してるとこ、無いですかね、
しっかりした、ソース見て勉強したいんですけど、
0404nobodyさん
02/03/12 04:53ID:52qV3w5q0〜100未満のランダムな数がくるぞ
(少数含むから、気をつけれ!)
0405nobodyさん
02/03/12 06:34ID:mNSx+HCB「更新」ボタンの無効化ってどうやるんですか?
0406nobodyさん
02/03/12 07:25ID:???・・・
0409nobodyさん
02/03/12 10:43ID:???それか、アプローダとかでリロードしないで欲しいとか。
0410nobodyさん
02/03/12 11:09ID:???0411370
02/03/12 11:10ID:???ふと思いついて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フラグが立っている模様。
これ、バグですよねぇ…。英語書ける方、誰か報告してくれないかな…。
0412405
02/03/12 13:34ID:eWSq/Ah6submitで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:???前回の内容と比較すれば?
それとcgiに書き込んだあと、htmlファイルにリダイレクトさせるとか。
そうすれば更新ボタン押してもhtmlファイルをGETするだけでしょ。
0415405
02/03/12 13:50ID:eWSq/Ah6ありがとうございます。
でも、すみません、リダイレクトって何ですか?
0417nobodyさん
02/03/12 14:11ID:???> チェックボックスを付けて、それがオフの場合投稿を弾いてメッセージを表示する
INPUT TYPE=checkbox とか、
フォームデータのデコード とか、
検索かけてみて、それでも解らなければそこを聞くのが良いんでない?
と初心者の俺が口を挟んでみるテスト。
0418nobodyさん
02/03/12 14:25ID:h6G3oh/xアドバイスありがとうございます。
かすってるサイトを発見したので、掲示板に応用するため試行錯誤してみようと思います。
0419nobodyさん
02/03/12 14:39ID:???初心者のくせに的確だぜ。
このままではわしの地位が・・・。
大きくなる前に潰しておかねばの・・・ふぉっふぉっふぉ。
と、何かを企ててみるテスト。
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:???プログラム組むのを仕事にしてる人からしたらメチャメチャだろうけど
自分なりに考えて掲示板組んでみたりしたもので。
やっぱり頭使って悩みながら覚えるのが一番上達早いかなと。。
>>417
あ、もし具体的な改造依頼するなら改造スレッドでよろしく。
スクリプト改造工房 Part4
http://pc.2ch.net/test/read.cgi/php/1012839651/
0422nobodyさん
02/03/12 14:57ID:h6G3oh/xそっちに行きます。スマソ
0424nobodyさん
02/03/12 15:16ID:???とりあえず、$aじゃなくて$FORM{'a'}とかじゃないのか?
0425nobodyさん
02/03/12 16:50ID:+eqUJIVRHTTPリクエストを送って反応がなかった場合スクリプト自体が止まってしまいます
リクエストを送って30秒間反応がない時には次の処理に行く といった処理をするにはどうすればよいのでしょうか?
0427425
02/03/12 17:19ID:???ありがとうございます。
0428nobodyさん
02/03/12 18:15ID:???Perlメモのファイルロックなど自前のファイルロックもありますが,
flockが使える環境ならできるだけflock使ったほうがいいんでしょうか?
0429nobodyさん
02/03/12 18:17ID:???読んだことないけど,このあたりは大きそう。
http://www.h14m.org/
http://tds.dive-in.to/
0431nobodyさん
02/03/12 18:20ID:???下手に自前でやるより信頼できると思われ。
WinNT環境だと,flock使ってもロックしないって話を聞いたことがあるような。ないような。
0432nobodyさん
02/03/12 19:57ID:???漏れも迷わず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:???マルチポストするくらいなら正規表現でも書いてろ。
0435ぼくフェロー
02/03/12 20:21ID:/5Jn0bAA0436428
02/03/12 20:44ID:???信頼性も自前<<flockなのか。
なら自前lockのメリットはプラットフォームの問題のみなのか。
素直にflock使うか・・・
0437ぼくメイト
02/03/12 20:51ID:???あ、こんなところでもお会いしましたね。記念に。
$tmp = $a;
$tmp++;
print "$a is num\n" if $tmp == $a+1;
0438nobodyさん
02/03/12 21:02ID:???>数値を表すことができる
↑この仕様がわかりませんが、
if ($a =~ /^([+-]?\d*\.?\d*)([eE][+-]\d+)?$/ and $1 !~ /^[.+-]*$/)
みたいな感じかな?
数字が(Perlの変数で表せないほど)たくさん並んでもマッチするけど・・・
0439nobodyさん
02/03/12 21:40ID:p/r//4Piこれで正しく判定できますか?
eval {flock DATA,1 or die $!};
print "flock使えません\n" if $@;
0440nobodyさん
02/03/12 22:52ID:???http://www.jp.qmail.org/q103/jman5/maildir.html
0441nobodyさん
02/03/12 23:18ID:???~~~~~~~~~~~~~~~~
0442nobodyさん
02/03/12 23:21ID:p/r//4Pihttp://www.adl.nii.ac.jp/~moro/unix-programmer/faq-j_3.html#SEC35
>flock()はBSD起源ですが現在ではほとんどの(但し全てではない)Unixで利用できます。
>単一のホストでは簡単で効果的ですが、NFSでは全く使えません。 これはファイル全体を
>ロックします。
>さらに紛らわしいことに、 ポピュラーなプログラミング言語Perlは
>必要であればそれ自身のflock()関数を実装し、 完全な移植性があるように
>見せかけています。
0443440
02/03/13 00:06ID:???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:???0449nobodyさん
02/03/13 00:42ID:???$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);
}
てのはどうでしょう。
0450449
02/03/13 00:47ID:???最初の%inverseへの代入は無駄でした・・・
foreach (sort {$score{$b}-$score{$a}} keys %score) {...}
てすればいいのねー。
0451448
02/03/13 01:08ID:???0454nobodyさん
02/03/13 01:16ID:???ソートだとこんな感じかな
並べ替えて,前の点数と同じなら同位,違うなら上から数えた順位。
while(<DATA>){
chomp;
($name,$score) = split /,/;
push @score, {name=>$name,score=>$score};
}
my $allrank = 1;
my($prevscore,$rank);
foreach(sort {$a->{score} <= $b->{score}} @score) {
$rank = $allrank if ($_->{score}!=$prevscore);
print "$rank位,$_->{name},$_->{score}点\n";
$allrank++;$prevscore=$_->{score};
}
__DATA__
ishida,80
inoue,70
gotou,70
satou,65
shibata,90
suzuki,80
0455nobodyさん
02/03/13 01:39ID:???@score = map { $_->[0] }
sort { $b->[1] <=> $a->[1] or $a->[0] cmp $b->[0] }
map { [$_, (split /,/)[1]] }
<DATA>;
叩き台にでもなれば。
0457448
02/03/13 01:48ID:???0458わんらいな−
02/03/13 02:13ID:???map {
do{
$ninzu++;
$rank = $ninzu if ($_->[1]!=$prevscore);
$prevscore=$_->[1];
};
[$rank, $_->[0], $_->[1]]
}
sort { $b->[1] <=> $a->[1] or $a->[0] cmp $b->[0] }
map { [split /,/] }
<DATA>
)
{print "$_->[0]位,$_->[1],$_->[2]\n"}
0459458
02/03/13 02:15ID:???0460nobodyさん
02/03/13 02:59ID:???0461nobodyさん
02/03/13 03:12ID:???print関数使った直後にデータが出力されるようになる。
指定しないと,ある程度出力データが貯まってから出力される。
http://tohoho.wakusei.ne.jp/wwwperl1.htm#Tokushu
0462nobodyさん
02/03/13 03:15ID:???0463444
02/03/13 03:43ID:MYvm6b7t>446-448さん
簡潔すぎて・・意図する所がわからず
悩みに悩んだ結果がこれですけど、これでいいですか??
参照はかなり苦手です。。しかも無名配列。。
でも、おかげさまでかなり勉強になりました。
結果はばっちりでした。
@data = <DATA> ;
@tmp = map {(split /,/)[1]} @data;
@data = @data[sort {$tmp[$b] <=> $tmp[$a]} 0 .. $#tmp];
foreach ( @data ) {
chomp ;
($name,$score) = split /,/ ;
push @r , [ $name , $score ] ;
}
$score = 101;
for($i = $j = 0; $i <= $#r; $i++){
if($r[$i]->[1] < $score){
$j = $i ;
$score = $r[$i]->[1];
}
$r[$i]->[2] = $j + 1 ;
}
for ( $i = 0 ; $i <= $#r ; $i++ ) {
print "$r[$i]->[2]位,$r[$i]->[0],$r[$i]->[1]点\n" ;
}
__DATA__
ishida,80
inoue,70
gotou,70
satou,65
shibata,90
suzuki,80
tanaka,80
0464444
02/03/13 03:43ID:MYvm6b7t結果が・・・
1位,shibata,90点
2位,tanaka,80点
2位,ishida,80点
2位,suzuki,80点
3位,gotou,70点
3位,inoue,70点
4位,satou,65点
みたいになります。。
やはりループの回数数えないといけないんですね。
それと「100点満点だとして」というのが
どこに影響してるのかよくわからないんです。。
>454さん
一番素直に理解できました。
ソートのとこの式がちょっとおかしかったですけど。
(sort {$b->{score} <=> $a->{score}} @score)
ですよね。
ともかく、皆さん本当にありがとうございました。
全部理解してテストするのに2時間程かかりました。
もっと勉強せねば。。
0465nobodyさん
02/03/13 03:44ID:XatxhEQY結果だけ表示したいんですけど、途中まで書いたんですけど、わからなくて…
$dir = '.';
opendir(DIR, $dir) or die;
@file = sort grep { /\d+\.html/i && -f "$dir/$_"} readdir(DIR);
closedir(DIR);
foreach(@file){
if( $_ =~ /<a href="http:\/\//i ){
s/co\.jp/ne\.jp/g;
print;
}
}
0466nobodyさん
02/03/13 04:27ID:???いや、単なる個人的意見ですが。
>>465
HTML::LinkExtor使うと簡単ですよ。
0467nobodyさん
02/03/13 04:32ID:???引数で指定されたディレクトリに移動して.をopendir
readdirを見ていき$_が
・ディレクトリなら再帰(引数は今見てる$_)
・HTMLファイルなら開いて痴漢してプリント
全部見終わったら..に移動
な関数を作る。でいいのでは?
465は自力でできそうな気がするのでわざとコードは書かない(w
0468nobodyさん
02/03/13 04:55ID:???foreach (@file) {
open FH, $_ or die $!;
while (<FH>) {
if (m{<a\s+href="(http://[^"]+\.co\.jp[^"]*)"}i) {
$1 =~ s/\.co\.jp/.ne.jp/g;
print "$1\n";
}
}
close FH;
}
--------------------
use IO::Dir;
use HTML::LinkExtor;
foreach (grep { /\.html$/i } IO::Dir->new(q/./)->read) {
my $parser = HTML::LinkExtor->new;
$parser->parse_file($_);
foreach my $elem ($parser->links) {
$elem->[0] eq q<a> or next;
while (@$elem) {
my ($attr, $value) = splice @$elem, 0, 2;
next unless $attr eq "href"
and $value =~ m{http://.+\.co\.jp/?}i;
$value =~ s/\.co\.jp/.ne.jp/g;
print $value, "\n";
}
}
}
双方とも動作確認無しですが。
0470470
02/03/13 08:13ID:DQ1JFad8以下のようにソートすると当然、文字コード順で愛知(アイチ)、
愛媛(アイヒメ)……という順番になります。([18]が住所です)
-----------------------------------------------------------
# 都道府県別にソート
if($sort == 3){
@LINES = sort { (split(/\,/,$a))[18] cmp (split(/\,/,$b))[18] } @LINES;
}
-----------------------------------------------------------
これを都道府県コード順にソートするにはどうしたらよろしい
でしょうか?
http://www2.odn.ne.jp/sasabomb/tables/jisx0401.html
もちろんCSVに都道府県コードは含まれていません。どなたか
ご教示よろしくおながいします。
0471nobodyさん
02/03/13 08:27ID:???47都道府県名をあなたが望む順番でリストに格納。
そのリストに従ってデータをソートするルーチンを書く。
愛媛も愛知も同じ愛である以上、一緒に並ぶのは当然。
0472ほい
02/03/13 09:55ID:68BwgqOIif($sort == 3){
$i = 0;
undef(%pref);
foreach $pref_name ('北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県',
'茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県','新潟県','富山県',
'石川県','福井県','山梨県','長野県','岐阜県','静岡県','愛知県','三重県','滋賀県',
'京都府','大阪府','兵庫県','奈良県','和歌山県','鳥取県','島根県','岡山県','広島県'
,'山口県','徳島県','香川県','愛媛県','高知県','福岡県','佐賀県','長崎県','熊本県'
,'大分県','宮崎県','鹿児島県','沖縄県') {
$pref{$pref_name} = $i++;
}
@LINES = map {$_->[0]}
sort {$pref{$a->[18]} <=> $pref{$b->[18]}}
map {[$_, split /,/]} @LINES;
}
0473nobodyさん
02/03/13 10:29ID:auK7WJtB残ってますよね。
掲示板作ってるんですが書きこみ後リロードすると二重投稿になっちゃうんですよ。
どうやって回避するんでしょうか?
0474nobodyさん
02/03/13 10:36ID:???1:投稿内容を直前のものと比較して、一致したら書き込み拒否する。
2:書き込み後Locationで別のページ(そのBBSでも問題なし)に飛ばす。
0475473
02/03/13 10:46ID:auK7WJtBありがとうございます。
1:は考えたんですがプログラム的にカッコよくないかと思ったので・・・
2:でやってみます。
助かりました。
0476nobodyさん
02/03/13 10:50ID:???ただし、2の場合、投稿ボタン2度押しには対応できないという事を忘れずに。
1ならそれも防いでくれるけどね。
0477473
02/03/13 11:06ID:???ええ!?そうなんですか?じゃあやっぱり1でやりますね。
どうせソースなんか僕しかみませんしね。
あ、でも、連続して削除する時のチェックボックスなんかは
間違いでなく一致しちゃうこともありますよね。
そこらへんの実践的なテクニックって皆さんどうやって習得されてるんでしょうか?
Perlは独学の方も多いと思いますが・・・
(ちなみに僕は元COBOLプログラマです)
0478nobodyさん
02/03/13 13:28ID:???レンタル掲示板を自分でやろうとすると、
どうすればいいのでしょうか?
プログラムは1個で、設定ファイルを顧客分つくるのでしょうか?
また、自分が借りているティーカップでは、
アドレスの拡張子がhtml になっています。
これ、なんでhtml なんでしょうか?
レンタルの仕組みと関係あるんでしょうか?
0479nobodyさん
02/03/13 13:38ID:???もっと基本的なところから勉強しないと問題外。
具体的にはHTMLタグとかから。
0482nobodyさん
02/03/13 15:16ID:nYyCnnqMhttp://www.hoge.com/cgi-bin/foo.cgi
というCGIに対して、
http://www.hoge.com/cgi-bin/foo.cgi?http://www.bar.com/aaa/bbb.txt
という風にURLを渡して、
bbb.txtの内容を読みこんであれこれ処理したいんですが、
bbb.txtの内容を読みこむにはどうやればいいんですか?
何かモジュールを使うんでしょうか。
■ このスレッドは過去ログ倉庫に格納されています