Perl コーディング初心者質問コーナー Part36
■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん
04/07/14 13:23ID:???【投稿する際の注意】
質問するときは内容をよく吟味してから投稿してください。
「コマンドの意味がわかんない」とかはマニュアル見ましょう。
回答者さんは何でも屋じゃありません。
1: 自分はこう言う事がしたい。
2: それでこんな風にやってみたが・・・
3: こんなエラーが出て上手く行かなかった。
最低でも1と3が無いと誰も答えられないよ。
ソース貼る時は、全角スペースでインデント忘れずに。
良い回答は良い質問から。一緒に勉強しましょう。
過去ログやお勧めサイトは >>2-10
0636nobodyさん
04/08/13 01:27ID:???自分でも書いているように、
正確には「印字可能」だからではなく、
単に \W にヒットしないからそのままPなだけ。
逆に、符号化する必要のない - とかまで符号化されちゃうけどね。
判って使う分には\Wで手抜きするのもOKなり。
0637nobodyさん
04/08/13 02:22ID:???0638nobodyさん
04/08/13 03:48ID:???戻り値やパフォーマンス、効率、map/forに限らず
副作用を期待したコードは出来るだけ避けた方が良いと思うんだけど。
>>628
>>622はmapの副作用の有無に関わらず、
@fooが変更されたと言うのがコードから読みとれる。
そもそも、そう言った用途にmapを使うなって話なら同意だけど、
もしmapを使うとしたら配列が変更されたのを明示するって例だと思う。
perl以外の言語を使っている立場から見ると、
mapが勝手に配列の要素を変更するのが気持ち悪いんじゃないかな?
例えば次のコード例で、barの引数 @data にはどんな値を期待するか。
foo(map s/A/B/, @data);
bar(@data);
0640nobodyさん
04/08/13 04:23ID:???藻前はTemplate::HTMLとか使わないで全部自分でHTML printするのかと。
0641nobodyさん
04/08/13 05:03ID:???可読性の話だよ。>>555 にあるように Perl コミュニティ的には、
何をしているのか分かり易くする為、副作用のみを利用する
ようなコーディングを奨めていない。
しかし (Perl スクリプトという手段の中で) 速度の為に可読性
を犠牲にしなければならない場面というのは確かにある。でも
そういう時でさえ map でやる意味が無い、という事をベンチ
マークが示している。それを理解できない子が吠えてるだけ。
>>640
HTML::Template の仕様が気持ち悪いから必要充分なものを
再発明、というのはありじゃないかな。
0642nobodyさん
04/08/13 05:18ID:???1.関数の一番最後の式は戻り値になるのでvoid contextじゃない。
2.mapの方だけブロックにするのは不公平。
use Benchmark;
timethese(-3,
{
map => sub{
my @list = 1..1000;
map $_ *= 2, @list;
1;
},
for => sub{
my @list = 1..1000;
$_ *= 2 for @list;
1;
},
}
);
Benchmark: running for, map for at least 3 CPU seconds...
for: 4 wallclock secs ( 3.23 usr + 0.00 sys = 3.23 CPU) @ 1535.91/s (n=4961)
map: 4 wallclock secs ( 3.24 usr + 0.00 sys = 3.24 CPU) @ 1577.47/s (n=5111)
0643570
04/08/13 05:33ID:ZD4WTWGN確かにね。投稿してからきずいたよ。
ただ、ベンチとったら633と同じような結果だったからどうでもいいと思ったんだ。
その2点に注意して、
Benchmark: running for, map for at least 5 CPU seconds...
for: 6 wallclock secs ( 5.42 usr + 0.00 sys = 5.42 CPU) @ 1520.10/s (n=8242)
map: 5 wallclock secs ( 5.03 usr + 0.00 sys = 5.03 CPU) @ 1534.68/s (n=7721)
C:\home\tenho\lavoratory\form>3.pl
Benchmark: running for, map for at least 5 CPU seconds...
for: 5 wallclock secs ( 5.42 usr + 0.00 sys = 5.42 CPU) @ 1520.10/s (n=8242)
map: 6 wallclock secs ( 5.50 usr + 0.02 sys = 5.52 CPU) @ 1486.58/s (n=8200)
C:\home\tenho\lavoratory\form>3.pl
Benchmark: running for, map for at least 5 CPU seconds...
for: 5 wallclock secs ( 5.23 usr + 0.00 sys = 5.23 CPU) @ 1529.42/s (n=8005)
map: 5 wallclock secs ( 5.48 usr + 0.00 sys = 5.48 CPU) @ 1495.26/s (n=8200)
C:\home\tenho\lavoratory\form>3.pl
Benchmark: running for, map for at least 5 CPU seconds...
for: 6 wallclock secs ( 5.50 usr + 0.00 sys = 5.50 CPU) @ 1502.36/s (n=8263)
map: 6 wallclock secs ( 5.53 usr + 0.00 sys = 5.53 CPU) @ 1482.28/s (n=8200)
0644nobodyさん
04/08/13 05:44ID:JjTi/TTmまったくの暗中模索状態なので検索ワードだけでもお教えいただければ幸いです。
よろしくおねがいします。
0645nobodyさん
04/08/13 06:03ID:???△▲ WebProg 初心者の質問 Part9 ▼▽
http://pc5.2ch.net/test/read.cgi/php/1086715675/
0646nobodyさん
04/08/13 06:15ID:JjTi/TTmありがとうございます。
過去ログ読んで、ないようなら移動します
0647nobodyさん
04/08/13 07:11ID:???関数自体が無効コンテキストで呼ばれるので、
戻り値を気にする必要はないと思うよ。
Benchmark.pm の runloop() 参照。
0648nobodyさん
04/08/13 09:10ID:???0649nobodyさん
04/08/13 11:56ID:???0650nobodyさん
04/08/13 12:14ID:???ソース公開するってんなら別だが。
Bench取る癖は悪かないが、mapとfor比べたってしょうがないだろ。
複雑な問題解決のためのアプローチの違いとかでやんなさい。
0651nobodyさん
04/08/13 12:35ID:???@math = ("0","1","2","3","4","5","6","7","8","9");
for($i=0;$i<@math;$i++){ $value =~ s/@math[$i]/$i/g }
ダサイ・・・・・・・
for($i=0;$i<10;$++){ $value =~ s/\xa3\xb$i/\x3$i/g }
こんなのがokなら一行ですむのに
0652nobodyさん
04/08/13 12:37ID:???上の方から気になってたんですが、思い切って質問することにしました。
foreachの速さを調べる時はforでベンチ取るんですか?
0654nobodyさん
04/08/13 12:58ID:???Perl では for ループも foreach ループも実体は同じ。
foreach (my $i = 0; $i < 5; $i++) { print $i }
for (5..9) { print }
但し "foreach" 修飾子は存在するが "for" 修飾子は
存在しないので、以下のような事はできない。
print $i for ($i = 0; $i < 5; $i++);
まぁ1つの文に ; が複数出てくる事になるので自明だけど。
0656652
04/08/13 13:16ID:???ありがとうございます。
for(@a){print}
print $_ for @a;
と
foreach(@a){print}
print $_ foreach @a;
両方使えるなんて知りませんでした。なんか今後foreach使わずにforだけでやってしまいそうですが
for(@a){print}ができるならforeachってあまり必要ないと思うんですが、そんなことはありませんか?
0657nobodyさん
04/08/13 13:56ID:???%a=( aa=>1 , a1=>1 , a3=>1 , ax=>1 , a8=>1 , a5=>1 );
このハッシュのキーを正規表現にかけて
/\w\d/
に真がでるキーが3個以上あればそれらに対して
delete $a{hoge};
をしたい。
とりあえずいまのとこ思ってるもの↓
@a = grep/\d\w/,keys %a;
undef $a[0] for 0..1;
delete $a{$_} for @a;
undefに配列スライスが使えないなんて知らなかった;
他にもコーディング案があったらレス下さい。
0658nobodyさん
04/08/13 13:58ID:???これは
undef $a[$_] for 0..1;
の間違いでした。
0659nobodyさん
04/08/13 14:28ID:???delete 対象の優先順位とかは無いの?
if ((my @key = grep /\w\d/, sort keys %a) > 2) {
delete @a{ @key[2..$#key] };
}
0660657
04/08/13 14:47ID:???優先順位はなし。消えればなんでもいい感じ。
delete @a{ @key[2..$#key] };
これいいね!@aってのがミソなのね。知らなかったよ。
ところで全然関係ないことなんだけど、HTMLタグのサニタイジングってどのタイミングでしてる?
今まで受け取って%formを作る際にしてたんだけど、それじゃちょっとよくないから
ちゃんと出力時||使用時にやろうと思うんだけど例えば
$form{hoge} まだサニタイジングしてない状態
$form{hoge} サニタイジング済み
にするべきか
$form{hoge} まだサニタイジングしてない状態
$hramless{hoge} サニタイジング済み
にするべきかなんだけど、やっぱり送られてきたデータの初期状態は残して置くべきだから
後者でやるべきだよね?
でもちょっとに大きくなってきたので(プログラムが)、きついんだよね。
0661nobodyさん
04/08/13 15:01ID:???俺は
read(STDIN.$buffer,$ENV{CONTENT_LENGTH});
foreach(split/&/,$buffer){
my($a,$b)=split/=/;
$b =~ s/%(..)/pack("H",$1)/;
$b =~ s/<>\:\;その他自分のサイトで必要ない記号//g;
$form{$a} =$b;
}
でやってる。いちいちその都度やってるとモジュール化もやりづらい。
0663nobodyさん
04/08/13 15:36ID:???0664nobodyさん
04/08/13 17:32ID:???0665nobodyさん
04/08/13 17:43ID:???呼び出し側からみたら第1っぽいからいんじゃね?
それよりここにいるやつのどれくらいがオブジェクト指向プログラミングできるのかね?
漏れは通販サイトの注文システムを一個の自作モジュールで、面倒andどのページでも使うような
処理をまとめようと思ったが、挫折したorz
どこまでをmainのオブジェクトにやらせて、どこからをモジュール側のオブジェクトにやらせるかの
境界線に苦悩して、最後は状態と振る舞いの境界(意味不明な言い方でごめん)までわからなくなって
結局ライブラリにして終らせた;
むずいんだよ!
0666nobodyさん
04/08/13 17:47ID:???お前はまずオブジェクトを何に見立てるかができてないんだろ?
例えばメインパッケージを注文を電話で聞くお姉さん。
モジュールの方を、お姉さんが使うパソコン。
とかな。まあお姉さんが注文が来るたびにパソコンを買う(new)なんてのはおかしな話だがなw
0667nobodyさん
04/08/13 18:17ID:???$hoge="hoge=1&data=a-a-a&test=23456";
この$valueの中からdata=a-a-aだけを取り出したいです。
data=a-a-aのある位置は毎回違うのでsubstrではできません。
data=に続く文字列も毎回違います。
splitとforeachを使って%formなどを作るのは禁止で、実現したいです。
$hoge =~ s/(data=.*?)&//;
$value = $1;
で一応data=...の後に&がある時は取り出しに成功できますが、
$hoge="hoge=1&data=a-a-a";
などの場合もあるのです。それと
$hoge="hoge=1&data=a-a-a&test=23456&tete=ussgf";
みたいな場合もあります。
どうにかどんなときでもdata=文字列だけを一発で取り出せないでしょうか?
0668nobodyさん
04/08/13 18:20ID:???if ($hoge =~ /data=.*&/){
$hoge =~ s/(data=.*?)&//;
$value = $1;
}else{
$hoge =~ s/(data=.*)//;
$value = $1;
}
ちと長いな。
0669nobodyさん
04/08/13 18:31ID:???0670nobodyさん
04/08/13 18:32ID:???0671667
04/08/13 18:42ID:???ありがとうございます
/(data=.*?)&?$/
これ不思議なコードですね;どうしてこれでうまくいくのかな。
$は&?にかかってるけど、&がないときは(data=.*?)にかかるって言う便利なコードですか?
・・・すごいですね>>669さんは。本当にすごいです。
0673667
04/08/13 18:48ID:???($value) = $hoge =~ s/(data=.*?)&?$//;
としたいんですが、置換にすると置換数?真偽?が帰ってくるので
$hoge =~ s/(data=.*?)&?$//;
$value = $1;
とするしかありませんか?一行でバチッとできるとカッコイイんですが。
ものすごく>>669さんからの返事が楽しみです^^(頼り切ってすみません;)
0675nobodyさん
04/08/13 19:02ID:???for my $hoge (qw(
hoge=1&data=a-a-a&test=23456
hoge=2&data=a-a-a
data=a-a-a&test=12345
)) {
my($value) = $hoge =~ /(?:^|&)(data=[^&]*)(?:&|$)/;
print "$value\n";
}
0677669※
04/08/13 19:03ID:???そして、ハシュを拒否する事由は?
my $hoge="hoge=1&data=a-a-a&test=23456&tete=ussgf";
my %hash = map +(split /=/), split /&/, $hoge;
printf qq|%s = %s\n|, $_, $hash{$_} foreach keys %hash;
env.:
$ perl5.8.5 -v
This is perl, v5.8.5 built for i686-linux
0680667
04/08/13 19:16ID:???/(?:^|&)(data=[^&]*)(?:&|$)/;
これは>>669さんのやつの変形ですか?でも>>669さんのコードで試したらちゃんと表示されましたよ?
テストが足りないんですかね?もう一度やってみます。
>>677
フォームで送られてくるデータを一度変数に入れて、その後
dataの部分だけをAルーチンに渡して、
それ以外をBルーチンに渡したかったのです。(ルーチンは外部ファイルに作ってあるます)
今はAルーチンとBルーチンの方で、ハッシュにする流れです。先にこちらでハッシュにしてわたしてもいいのですが、
こういうのもできたらカッコイイなと思って質問いたしました。
0682667
04/08/13 19:23ID:???hoge=1&data=a-a-a&test=23456
hoge=2&data=a-a-a
data=a-a-a&test=12345
)) {
($value) = $hoge =~ /(data=.*?)&?$/;
print "$value<br>";
}
>data=a-a-a&test=23456
>data=a-a-a
>data=a-a-a&test=12345
>>676
さっきはうまくいったと思いましたが、↑のソースでやってみたらうまくいきませんでした;
ちゃんとテストしたつもりが勘違いでした;
>>皆様
もの凄く勉強になりました!本当にありがとうございました!それでは失礼します。
0684nobodyさん
04/08/13 19:37ID:???オブジェクト指向で書く場合は俺はサニタイジングモードを作ってるよ。
sub new {
my $self = shift;
my $buffer = shift;
my %harmless_mode = (
normal => 1,
html => 0,
sql => 0,
csv => 0,
);
みたいなね。(1=on,0=of)
んで状態移行のメソッドを作っておけば一応問題ないかな。まあ俺は小規模プログラムしかやったことないから
大丈夫なだけかもねw
0685nobodyさん
04/08/13 20:13ID:???確かに >>667 のは \b で充分だね。分かって言ってるんだろうけど一応。
for my $hoge (
"hoge=1&data=a-a-a&test=23456",
"hoge=2&a-data=a-a-a&test=12345",
"data=a-a-a\n",
) {
my($value1) = $hoge =~ /\b(data=[^&]*)/;
my($value2) = $hoge =~ /(?:^|&)(data=[^&]*?)(?:&|$)/;
print "1[$value1] 2[$value2]\n";
}
0688nobodyさん
04/08/13 20:55ID:???sub new{
my $this = shift;
my $propety = {
color => shift,
weight => shift,
};
bless $propety,$this;
}
ていうコンストラクタだったとして、あとから他のメソッドで
sub change{
my $this = shift;
$this->{color} = "red";
$this->{changed} = "1";
}
みたいにコンストラクタではなかったchangedっていうプロパティをいきなり作っちゃっていいんですか?
それとも、コンストラクタを
$propety = {
color => shift,
weight => shift,
changed => 0,
};
みたいにするべきでしょうか?そうしてしまうと新しいプロパティがほしくなった時に
わざわざコンストラクタをいじらなければいけなくて、不便かなと思うんですが・・・
0689683
04/08/13 21:00ID:???ウソ!?って思って試してみた。
for my $hoge (qw(
hoge=1&data=a-a-a&test=23456
hoge=2&data=a-a-a
data=a-a-a&test=12345
)) {
$str = ($hoge =~ s/\b(data=[^&]*)//, $1);
print "$str\n";
}
PCに入ってるPerlでも動かなかったw
0690nobodyさん
04/08/13 21:25ID:???そのコードの$hogeはReadOnlyな文字列への別名だから、
置換できるわけなかろう。
$hogeをループ先頭でmy $hoge=$_;とすりゃ動いたぞ。(Perl5.8)
#つか、foreachであるべきところをケチってforにすんな、紛らわしい。
ちなみに>>685の問題も回避したい場合、
置換では>>675でもうまくいかんので、
$str = ($hoge =~ s/(?:^|(?<=&))(data=[^&]*)//, $1);
とするといい。
#後ろの(?:&|$)はいらんべ?
0691nobodyさん
04/08/13 21:57ID:???作法として行儀がいいかどうかは別として、blessされてる以外は
ただのハッシュだからキーの追加だろうが削除だろうが自由にでき
ます。
use fields使ってりゃ別だけどな〜
0692688
04/08/13 22:39ID:vpkCloyFできるのは知ってるのですが、どうするのが一番「十分に拡張的なプログラム」なのかで悩んでます。
0693nobodyさん
04/08/13 23:27ID:???一番かどうかはともかく一つのやり方として。
コンストラクタでは何もせず、プロパティは全てアクセサ経由で触り、
初期値はアクセサで設定する。
#--- Foo.pm ---
package Foo;
sub new {
my $class = shift;
bless { @_ }, $class;
}
sub color {
my $self = shift;
@_ or return $self->{'-color'} ||= 'red';
$self->{'-color'} = shift;
$self;
}
1;
#--- script ---
use Foo;
my @obj = (Foo->new, Foo->new(-color => 'green'), Foo->new);
$obj[2]->color('blue');
print $_->color, "\n" for @obj;
0694nobodyさん
04/08/13 23:34ID:Dbtrqa9I喧嘩を売っています
0695nobodyさん
04/08/14 03:15ID:HZTk9WgD普通にファイルオープンの open(AAA,"<BBB.txt") のように開いて
データを取得することが出切るのでしょうか?
検索で、解説ページなどを探したのですが良いサイトが見つかりません。
(探し方が悪いだけかもしれませんが・・・・)
どこか良いサイトなどがありましたら、教えてください。
0696nobodyさん
04/08/14 03:19ID:???0697688
04/08/14 10:22ID:???例まで書いていただいてありがとうございます。
買う時には必要でなかったプロパティが、買ってから途中でほしくなった場合のために
プロパティを後から追加できるオブジェクトメソッドを作っておいたらオブジェクト指向の利点がどこかで
失われてしまいますか?
sub additional_propety {
my $class = shift;
$class->{shift} = shift;
}
第2、第3引数に新規に追加するプロパティとその値を期待します。
0698nobodyさん
04/08/14 10:39ID:???そもそもコンストラクタ(new)を「買う」ことだと思ってる時点で、間違ってるな。
まあよくある解説だけどw
人に置き換えて考えてみ?例えば友達に「ジュース買ってきて」って頼むだろ。
そんでその友達がジュースをkって来るのは友達にはそういう振る舞いができるってこと
で、お前はその友達のインターフェースさえ知っていれば何度でもジュースを買ってきてもらえるんだ(買ってこない友達の状態もあるけどな)。
んでこんな時に new=買う ではおかしいだろ?だから new=自分と同一世界にいると認識する
なわけよ。だから認識さえすれば、人の家のテレビだって使えるわけだ。これが自然。
0699nobodyさん
04/08/14 11:03ID:???0702nobodyさん
04/08/14 15:31ID:???$sub
$exit{for}
ここらへんがPerlのいいところですか?(Perlとmysqlしか知らないのでよくわかりませんが、すくなくともSQLでは予約語はdb_name,tbl_name,columns_nameには使えなかった気がしたので)
0703nobodyさん
04/08/14 15:35ID:???0704nobodyさん
04/08/14 15:52ID:???a => 1,
b => 2,
c => 3,
};
このハッシュのキーと値を「=」でjoinして、さらにそれを「&」でjoinしたいんです。
my @a;
foreach (keys %$test)
{ @a = $_."=".$test->{$_} }
$ok = join '*',@a;
undef @a;
わざわざ@aに一度入れるのが、冗長な気がするんですがいれない方法はありますでしょうか?
0706704
04/08/14 16:03ID:???$a = join "&",map{$_."=".$test->{$_}} keys %$test;
0707nobodyさん
04/08/14 16:24ID:???と
$a == undefined && $a =1;
と
if($a == undefined){ $a == 1 }
これってどれが一般的に可読性がよいのですか?僕は結構真ん中の書き方がすきなのですが
みんなでプログラムを組む時などにはどれを使うと喜ばれますか?
0708nobodyさん
04/08/14 16:27ID:???0711nobodyさん
04/08/14 16:55ID:???0712695
04/08/14 17:13ID:HZTk9WgD見つかりはするんですが、内容が難しかったり、関係無いものだったり・・・
わかりやすいページを見つけるにはどういった単語で検索すれば良いのでしょう?
0713nobodyさん
04/08/14 17:20ID:???undefinedじゃなくてundefだろ。
そういうミスを use strict が警告してくれるんだよ。
ちなみに普通はundefは使わず、それぞれ
$a = 1 if ! defined $a;
defined $a or $a = 1;
if (! defined $a) { $a = 1 }
のようにdefinedを使って書く。
また、if ! の代わりにunlessを使って
$a = 1 unless defined $a;
unless (defined $a) { $a = 1 }
のようにも書けるが、一般的にunlessやuntilなどの否定条件文は理解の
妨げになることが多いので使われない。
if ! より字数が多いのもネック。
で、or(または||)やand(または&&)を利用した「式1 or 式2」のような
記述は、副作用を持つ式1の結果如何で式2を評価するというものなので、
副作用のないただの条件式を式1に使うことはない。
#openがよい例
やるなら後付けif文か通常のif文かだが、今は$a=1しかすることが
なくても、後々他の処理も追加する可能性が少しでもあるなら
通常のif文を使うべき。
長文スマソ
0715nobodyさん
04/08/14 17:27ID:???>見つかりはするんですが、内容が難しかったり、
難しいんじゃなくてそれが普通なんだよ。
藻前には無理ってことだからあきらめろ。
0716nobodyさん
04/08/14 17:45ID:???undefined間違えてすみません。
でも聞く限りではuse strictはやっぱり無駄なモジュールなんですね。
一応文法チェックかけるんでそれで十分だと思います。というか何故に毎回そんなモジュールを読み込む必要が
あるのか?です。なんかアフォぽです。
0719nobodyさん
04/08/14 17:55ID:???はstrict.pmとかvars.pmとか色々読み込むので確かに遅くはなりますが、
$a == undefinedとか書いちゃうようなバカにはちょっと遅いくらいが
ちょうどいいと思いますよ。ほんと。
0721nobodyさん
04/08/14 18:07ID:???use strict; に厳しい添削をしてもらって完成したコードが
エラーや警告出なくなったらお引取り願えばいいことも
わからないバカは(ry
0724711
04/08/14 18:15ID:???@a = qw/1 2 3 4/;
$a = "absnd";
%a = (a => 1);
(%a , $a , @a) = undef;
print "$a\n",%a,"\n@a";
これだけできました。でも一応
(%a , $a , @a) = (undef) x 3;
とかしたほうがいいですか?
0725nobodyさん
04/08/14 18:17ID:???0729nobodyさん
04/08/14 18:36ID:???0730nobodyさん
04/08/14 18:44ID:???0734nobodyさん
04/08/14 19:25ID:???0735nobodyさん
04/08/14 19:33ID:???0736724
04/08/14 19:33ID:???それでもできるんですね。
>>733
代入できても、やってはいけないことなのでしょうか?
(%a , $a , @a) = (undef x 3);
これが一番ですか?
■ このスレッドは過去ログ倉庫に格納されています