Perl コーディング初心者質問コーナー Part36
■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん
04/07/14 13:23ID:???【投稿する際の注意】
質問するときは内容をよく吟味してから投稿してください。
「コマンドの意味がわかんない」とかはマニュアル見ましょう。
回答者さんは何でも屋じゃありません。
1: 自分はこう言う事がしたい。
2: それでこんな風にやってみたが・・・
3: こんなエラーが出て上手く行かなかった。
最低でも1と3が無いと誰も答えられないよ。
ソース貼る時は、全角スペースでインデント忘れずに。
良い回答は良い質問から。一緒に勉強しましょう。
過去ログやお勧めサイトは >>2-10
0021nobodyさん
04/07/15 14:16ID:???不正のある行数を配列に格納する部分まではできるのですが、それの表示方法で質問です。
@err_lineの中身が("1","3","5")だとした場合、「1,3,5行目の書式が不正です」と表示するエラー画面を出したいのですが、
foreach(@err_line){
print $_ , ",";
}
print "行目の書式が不正です"
とすると、「1,3,5,行目の〜」となり、配列の最後の文字を出力した後にも","(カンマ)が出力されてしまいます。
何か良い書き方はないでしょうか。
0025nobodyさん
04/07/15 14:51ID:???0027nobodyさん
04/07/15 14:58ID:???なぜなら絶対パスへの変換はWWWサーバの設定によって違い、
perl はサーバの設定がどうなっているかを知らないから。
ASPはIISと一体となっているから変換できる。
mod_perl なら Apache::* モジュールでなんかそういうのがあるかも。
0028nobodyさん
04/07/15 16:43ID:???なぜなら絶対パスへの変換はWWWサーバの設定によって違い、
perl はサーバの設定がどうなっているかを知らないから。
ASPはIISと一体となっているから変換できる。
KENT なら CGIでなんかそういうのがあるかも。
0029nobodyさん
04/07/15 18:20ID:???まじめに考えてみると難しいな
単純に頭に DocumentRoot をつけるだけなら楽だが
mod_rewrite とか使われた日には目も当てられない
mod_perl の環境に限定だが、サブリクエストを使って
$filename = Apache->request->lookup_uri($uri)->filename;
とかやれば、ほとんどの場合は変換できるんじゃないかと思う
Reverse Proxy だったりした場合には何が起きるか保証できないが
0030nobodyさん
04/07/15 18:50ID:???PerlってASPやJavaみたいにアプリケーションサーバ込みで考える開発環境じゃないんだよね。
だから関数で実現するんじゃなくって、別のソリューションを見つけるべきだね。
003125
04/07/15 18:54ID:???コピペして保存させていただきます!
0032nobodyさん
04/07/15 23:15ID:???以下のようなコードを書きました。
$total = (split(/,/,$a) * 3)+(split(/,/,$b) * 2)+(split(/,/,$c) * 1);
で、perl -cw すると以下のような警告が出てしまいます。
Use of implicit split to @_ is deprecated at test.pl line xx
どうすればこの警告が出ないようになるのでしょうか?
0033nobodyさん
04/07/15 23:25ID:???0034nobodyさん
04/07/15 23:36ID:???@a = split(/,/, $a);
@b = split(/,/, $b);
@c = split(/,/, $c);
$total = (@a * 3) + (@b * 2) + (@c * 1);
# クドいな(汗)。
明示的に配列に突っ込んだりすると出なくなる仕組み。
0035nobodyさん
04/07/15 23:45ID:???>>33
> scalar(split(/,/,$x))
これをやってみましたが、同じエラーが出ました...
やっぱり地道に
>>32
のようにするしかないのですかね。
0037nobodyさん
04/07/15 23:56ID:???splitの結果何が返って来るのかね?んー?
003834
04/07/16 00:05ID:???最近、perl.exeを入れてみたところ。
C:\Documents and Settings\hoge>perl -cw %home%\test2.pl
Use of implicit split to @_ is deprecated at C:\home\hoge\test2.pl line 5.
Use of implicit split to @_ is deprecated at C:\home\hoge\test2.pl line 5.
Use of implicit split to @_ is deprecated at C:\home\hoge\test2.pl line 5.
C:\home\hoge\test2.pl syntax OK
# 元コードの、split() が @_ に implicit に代入されてるとこが line 5。
こんな感じです。>>37
0039≠37
04/07/16 03:30ID:???> splitの結果何が返って来るのかね?んー?
は試してみた?
>要素の「数」でポイントを出したくて
ということなら、
my $a = ("fred","wilma","barney");
my $b = ("hoge","hogehoge");
my $c = ("2","6","8","9");
print split/,/,$a;
print split/,/,$b;
print split/,/,$c;
my @a = ("fred","wilma","barney");
my @b = ("hoge","hogehoge");
my @c = ("2","6","8","9");
print split/,/,@a;
print split/,/,@b;
print split/,/,@c;
上の二つ比べてみ。
0040nobodyさん
04/07/16 03:53ID:???問題を読み違えているぞ。
$a = 'fred,wilma,barney';
$aa = split(/,/, $a);
print $aa;
splitをスカラで受けた場合に
「Use of implicit split to @_ is deprecated」警告が出るという話。
0041nobodyさん
04/07/16 04:08ID:???>splitの結果何が返って来るのかね?んー?
もしかしてsplitをスカラで受けた結果何が返ってくるか知らないのかね?んー?
004234 != 32
04/07/16 04:35ID:???質問者さんの「$a,$b,$cの中でカンマに区切られている要素の数」を、
my $a = "fred,wilma,barney"; # これを「カンマに区切られている要素」と呼んでるのかな、と。
my $b = "hoge,hogehoge";
my $c = "2,6,8,9";
print scalar(split(/,/,$a));
print scalar(split(/,/,$b));
print scalar(split(/,/,$c));
こういうのを想定して>>34を書きました。>>22を書いたのも自分なので、その記憶もあり。
>>39は、
ex1. 'barneyhogehoge9' # 最終の要素。手前のsplitがなくても、同じ結果に。
ex2. '324' # 要素の「数」。
という出力になりました。
あっ、>>37さんの「splitの結果何が返って来るのかね?」は、
>>32だと $total = 1 * 3 + 1 * 2 + 1 * 1 で固定やぞ、ということなんでしょうか?>>39さん
質問者じゃないのに、何を混乱してるんだろう(泣)。
004334
04/07/16 04:40ID:???元質を見て想定してたのは>>40さんと同じ。
>>37さん、>>39さんのお話の意図がつかめなくて
マゴマゴしてしまいました(汗)。
004534
04/07/16 05:07ID:???ありがとうございます。元々、>>40さん、>>44さんと同じように考えてたはずが、
>>39を見て「俺、何かとんでもない勘違いしてたんだろうか?」と不安になってました。
# 慌てて書いたので>>42のコードだと…同じ警告を吐くような。
とりあえず、頭冷やします。
0046nobodyさん
04/07/16 08:41ID:???警告メッセージは、@_ への暗黙な代入を警告しているだけだから
警告が特に問題ないとわかっている場合は、
オプションを切ってもいいんじゃない?
{ no warnings;
$count = split(/,/,$a) * 3 + split(/,/,$b) * 2 + split(/,/,$c);
}
no warningを使う場合は、必ずブロックで局所化する事と、
警告オプションを切ったブロックないで
組み込み関数以外の他のサブルーチンの使用に注意する。
明示的に配列に代入する でも回避できるみたい。
3 * (@_=split/,/,$a) + 2 * (@_=split/,/,$b) * (@_=split/,/,$c);
0047nobodyさん
04/07/16 09:12ID:???my $b = 'hoge,fuga'; # 2 * 2
my $c = '1,2,3,4,5,6,7'; # 1 * 7
my $total = (1 + $a =~ tr/,//) * 3
+ (1 + $b =~ tr/,//) * 2
+ (1 + $c =~ tr/,//)
; # 20
0051nobodyさん
04/07/16 13:52ID:???こういう事を言いたいのかな?
#--- test1.p ---
my @str = ('1,,,,', ',,,,1', ',,1,,', '');
print 0 + @{[split /,/]} for @str; # 1530
print "\n";
print 1 + tr/,// for @str; # 5551
print "\n";
print 0 + (length && 1 + tr/,//) for @str; # 5550
#--- test2.p ---
use Benchmark;
our @str = ('foo,bar,baz', 'hoge,fuga,' x 5, ',,,,1', ',,1,,', '1,,,,', '');
timethese(-5, {
split => sub { my $n = @{[split /,/]} for @str },
tr => sub { my $n = 1 + tr/,// for @str },
length => sub { my $n = length && 1 + tr/,// for @str },
});
005232
04/07/16 15:17ID:???みなさんありがとうございます。勉強になりました。
>>46 さんの
> 3 * (@_=split/,/,$a) + 2 * (@_=split/,/,$b) * (@_=split/,/,$c);
>>47 さんの
my $total = (1 + $a =~ tr/,//) * 3
+ (1 + $b =~ tr/,//) * 2
+ (1 + $c =~ tr/,//)
; # 20
あたりが良さそうですね。ちょっと今から試してみます。
>>47 は、コード読んでもなんでそうなるのかよくわからない...
0053nobodyさん
04/07/16 16:35ID:???http://flex.ee.uec.ac.jp/texi/perl/perl_103.html
005532
04/07/16 17:04ID:???> 3 * (@_=split/,/,$a) + 2 * (@_=split/,/,$b) * (@_=split/,/,$c);
これやってみましたが、同じエラーがでました。???
これからtrの方を試してみます。
0057nobodyさん
04/07/16 19:49ID:???0058nobodyさん
04/07/16 19:56ID:wqtiPvAW0059nobodyさん
04/07/16 20:04ID:???フォローthx you, なるほど @{[split/,/,$a]} でもいいのか。
詳細を書くと、
'' を要素数0とカウントするか空文字1要素とカウントするか、という事ですが
他にも 'a,b,c' と 'a,b,c,' の様な場合、数え方で結果がかわってきます。
shiftでは末尾の空要素はなくなるが、tr, lengthの方法だとカウントされる。
一見同じ様に見えても、細部で微妙に仕様が変わってくるので注意しようってとです。
use strict;
use warnings;
my $a = '';
my $b = 'a,b,c';
my $c = '1,2,3,4,5,6,';
sub count_item_1($) { return int @{[split/,/,$_[0]]} }
sub count_item_2($) { return int 1 + $_[0] =~ tr/,// }
sub count_item_3($) { return int length $_[0] && 1 + $_[0] =~ tr/,// }
sub count(&) {
my($func) = @_;
printf("%d %d %d\n", $func->($a), $func->($b), $func->($c));
}
count(\&count_item_1); # 0 3 6
count(\&count_item_2); # 1 3 7
count(\&count_item_3); # 0 3 7
>>56
自分の環境(perl 5.6.1, perl 5.8.2 build for linux)ではこの方法で警告消えたのだけど、どうしてだろ。
0060nobodyさん
04/07/17 12:40ID:???あったはずなんだけどご存知ないでしょうか??
0061名無しさん
04/07/17 14:06ID:BYFAIbz8他のセッションに影響しないように注意するけど、Perlはそういう心配しなくていいの?
0063名無しさん
04/07/17 14:44ID:BYFAIbz80064nobodyさん
04/07/17 14:57ID:???利用するフレームワーク (CGI、mod_perl、FastCGI、
SpeedyCGI、PerlScript etc. etc.) に依る。
0065名無しさん
04/07/17 15:43ID:BYFAIbz80066nobodyさん
04/07/17 19:32ID:???セッションサービスの仕様はそのクラスによる。
つーか、Perlには標準でセッション関数はない。だから、自分で書くなり、そういうモジュールを探してくる。
0067nobodyさん
04/07/17 20:54ID:ihUsGdG4と入力されたデータを受け取って
$a="aaa";
$b="bbb";
という二つのデータに分けたいんだけど
$id(入力されたデータ)=~s/$1\/$2/$1$2/i;
$a="$1";
$b="$2";
とやってもうまく行かない
悪い点があったら教えて下さい
0072nobodyさん
04/07/18 05:14ID:???1〜1000の各数字が、5・6・7・8・9の5種のうちのどれかを所持しております。
所持するものの違いにより
1〜1000の数字をそれぞれ5つの配列に、分けるにはどうすればいいのでしょうか?
ずーーーーっと考えてるんですが、限界なので質問させてください。
0073nobodyさん
04/07/18 05:58ID:???0075nobodyさん
04/07/18 07:57ID:???ここがよくわからん
0076nobodyさん
04/07/18 08:34ID:???0077nobodyさん
04/07/18 09:59ID:???data[1〜1000] にそれぞれ5〜9の値が入っていて、
その値に応じて新しい配列(5個)を生成したい、
ってことだと思う。
>>74のいうようにpushとifでできるやぁね
0078nobodyさん
04/07/18 11:04ID:???0079nobodyさん
04/07/18 12:02ID:???効率なんて考えていないので添削キボンヌm(_ _)m
# 5,6,7,8,9 の数字が 1000 個入っている配列(リスト)
# 仮に rand を使って生成。
my @Source_array = map { ((5..9)[int rand 5]) } 1 .. 1000;
# を、それぞれ値 (5 〜 9) によって選別したい。
# でも 5 つも配列を作るのは、のちのちややこしくなるので、ここは 1 つの配列に格納して、
# それぞれを呼び出しやすくする。(リストリファレンスが 5 つ入っているハシュにする)
my %Dist_hash;
push @{$Dist_hash{$Source_array[$_]}}, $_ foreach 0 .. $#Source_array;
# 呼び出し方。
# 値が 7 の @Source_array の添え字を表示する。
my $value = 7; # 範囲は 5 から 9 の間で指定しる。
printf qq|\$Source_array[%s]\n|, join(', ', @{$Dist_hash{$value}});
# 実際に @Source_array の値を表示してみる。
printf qq|\$Source_array[%d] = %d\n|, $_, $Source_array[$_] foreach (@{$Dist_hash{$value}});
008072
04/07/18 14:14ID:???意図してたのはまさに77氏の言うとおりです。
79さんどうも!思ってたことができました。こんなの自分で考え付けるようになりたい。
ありがとうございました。
0081nobodyさん
04/07/18 22:22ID:LXS4mDIw@bb = qw[1 2 3];
$cc = "cc";
&hoge($aa,@bb,$cc);
sub hoge($,@,$){
my $aa = shift;
my @bb = shift;
my $cc = shift;
print "$aa \n";
print "$_\n" foreach(@bb);
print "$cc\n";
}
関数に変数と配列を渡し、関数側でそれぞれ上記のように
スカラ変数と配列を区別させて認識させたいのですが
どのようにすれば良いのでしょうか?
よろしくお願いします。
0082nobodyさん
04/07/18 22:25ID:???リファレンス使え。
0083nobodyさん
04/07/18 22:29ID:???http://www.kt.rim.or.jp/%7Ekbk/perl5.005/perlsub.html#Pass_by_Reference
008481
04/07/18 22:30ID:???もし使わずに実現できる方法があれば教えてほしいです。
0085nobodyさん
04/07/18 22:34ID:???動かしたいと考えています。perlを使ったCGIで
ルートユーザかしか使えないコマンドを
入力する方法はないでしょうか?
今、自分が作っているCGIの前に人が作った
認証を通す必要があり、ユーザは自分が指定した
一般ユーザでログインしているという形になります。
通常のコマンドであればシングルコーティションで
囲えばよいことがわかっているのですが、当たり前
ながら一般ユーザではroot専用のコマンドは
入力できません。
方法がありましたら、教えてください
0086nobodyさん
04/07/18 22:51ID:???0087nobodyさん
04/07/18 22:55ID:???配列が一番後ろなら出来る。
が、リファレンスを使った方が問題が起こりにくい。
リファレンスを使わずにやるなら、複雑な方法になるか、問題の起こりやすい方法になるかどっちかだ。
0088黒死犬 ◆EgxBlf8nvc
04/07/18 23:00ID:???Perl5.8以上なら
sub hogging($\[@]$) {
my $top = shift;
my @middle = @{+shift};
my $bottom = shift;
print("top = [$top]");
print("middle = [@{[join(',',@middle)]}]");
print("bottom = [$bottom]");
}
my @unko = (A..Z);
test("Test Start", @unko, "Test End");
これで出来ますよ
0089黒死犬 ◆EgxBlf8nvc
04/07/18 23:02ID:???s/test/hogging/;
0090nobodyさん
04/07/18 23:51ID:???プロトタイプ宣言は 5.002 から利用可能だが。
sub test($\@$) {
my $top = shift;
my @middle = @{+shift};
my $bottom = shift;
...
0091nobodyさん
04/07/19 00:02ID:???hoge($aa,@bb,$cc,@dd) みたく配列が二つ以上ある場合でもできたりします?
0092nobodyさん
04/07/19 00:08ID:???確認ぐらい人に聞かなくてもできるでしょ?
http://www.kt.rim.or.jp/%7Ekbk/perl5.005/perlsub.html#Prototypes
0094黒死犬 ◆EgxBlf8nvc
04/07/19 13:14ID:???そうなんですか
自分が情報を得ているところでは、[Perl5.8の新機能]となっていた為、誤解をしてしまった様です
ご指摘有難うございます
0095nobodyさん
04/07/19 16:08ID:???0096nobodyさん
04/07/19 21:58ID:54seOava上手く書き込めません。
同じ行に表示されるようにしたいんですが、次の行に改行されてしまいます。
上手く、一つのセルに改行したデータを入れたいんですが、どうすればよいでしょうか?
コードは、下のようなのを使っているのですが・・・・
根本的に間違ってたりするんでしょうか?
$aaa = '123';
$bbb = '456';
@ccc = '789',
'0123';
open(LOGFILE,">>log.csv");
$LOG = "$aaa,$bbb,@ccc";
print LOGFILE $LOG;
close LOGFILE;
0097nobodyさん
04/07/19 22:13ID:???Excelで表示する時の話?セルっつーのが何のことやら。
特定のアプリでの表示の話なら、
逆にそのアプリで改行して保存したものを覗いてみれば分かると思われ。
0098nobodyさん
04/07/19 22:27ID:54seOavaExcelで開いた場合です。説明不足ですみません。
メモ帳で開くと、改行のコードの問題みたいです。
改行コードの変換は
$ccc =~ s/\n/\r/g;
で良いんでしょうか?
0099nobodyさん
04/07/19 22:32ID:OSilZxWFperlコーディングには関係ないが
CSV形式では普通セル内に改行やカンマがあるときは「"」で囲うよ。
で「"」内では「"」を「""」で表現する
それからエクセルではセル内の改行は\r\nではなくて\n
0100nobodyさん
04/07/19 23:24ID:54seOavaエクセル内の改行は\nなんでしょうか?
とすると、
$ccc =~ s/?/\n/g;
「?」の部分には何を入れればよいのでしょう?
上記のように、s/\n/\r/g; として書き込んだファイルを
メモ帳で開くと、見た目はUNIX改行コードっぽくなっているのですが、
エクセルで開くと、セル内改行が出来ていないようです・・・
0101nobodyさん
04/07/19 23:56ID:???1 │3 │4
2 │ │
─┼─┼─
5 │6 │7
│ │8
↓
"1\n2",3,4\r\n5,6,"7\n8"\r\n
あとメモ帳じゃなくてバイナリエディタ使ってみな。
0102nobodyさん
04/07/19 23:59ID:???http://www.din.or.jp/~ohzaki/perl.htm#CRLF_Unify
0103nobodyさん
04/07/20 13:48ID:???ロケットマウスというソフトの設定ファイルをperlで生成して出力させようと
思ったのですが
ロケットマウスでは記号(){},+^~%`と半角スペースは特殊文字として
認識されてしまうのでメタキャラとして設定ファイルとして書き込む場合には
「+あかさたな+」という文字列では
「{+}あかさたな{+}」と置換してからファイルに書き込むようにしなければならないので
my $Name_T = '+あかさたな+';
my $Name_T = ~s/+/{+}/g;
のように置換できたのですが
「+-あかさたな-+」のようなものを上に書いたような形で一発で置換する
ことはできないのでしょうか?
最悪一つ一つ置換していけばOKなのですができればスマートに
できたら幸せになれます。
どうぞよろしくお願いします。
0104nobodyさん
04/07/20 14:08ID:???s/([\x20(){},+^~%`])/{$1}/g;
http://www5a.biglobe.ne.jp/~n_rieko/perl/8.htm
http://www.kt.rim.or.jp/%7Ekbk/perl5.005/perlre.html
WebProg と関係無い Perl の話はム板のスレへ。
http://pc5.2ch.net/test/read.cgi/tech/1085564875/
0105103
04/07/20 14:24ID:???勉強になります。
次からはム板でさせていただきます。
0106nobodyさん
04/07/22 07:13ID:???@data=<DATA>;
close(DATA);
foreach $data( @data ) {
とやって、同じディレクトリのindex.htmlを読み出して、携帯電話対応に書き換えるスクリプトを作ってたんですが、
ヘッダーをつける
<body>という文字列が見つかるまで、$data = '';に書き換える
次の$dataから書き出す
</body>が見つかったらそれ以降を$data = '';に書き換える
フッターをつける
とやってたんですが、なんか回りくどい気もします。
ヘッダ、body要素の中身、フッタを簡単に分ける方法ってないですかね。
0107106
04/07/22 07:43ID:???@dataから一行ずつ引っ張り出した、<body>〜</body>の$dataを@bodyに格納したいんですが、
$dataを書き直して、@bodyに入れていく、の方法がわかりません。
$dataを書き直して吐き出す、までは出来てるんですけど。
#@bodyをバイト数で割って、「次のページ」というのをやりたいんです。
0108106
04/07/22 08:06ID:???で出来ました……。板汚しごめんなさい。
0109nobodyさん
04/07/22 09:18ID:0RDyhyxo$data .= $_ while read(DATA,$_,1024);
close(DATA);
if ($data =~ m{<\s*body.*?/body\s*>}i) {
$head = $`;
$body = $&;
$foot = $';
}
0110nobodyさん
04/07/22 13:24ID:???#!/usr/local/bin/perl
use strict;
my @body;
m|<body>| .. m|</body>| and push @body, $_ while <DATA>;
shift @body; # <body> を捨てる
pop @body; # </body> を捨てる
print @body;
__DATA__
<html>
<head><title>test</title></head>
<body>
<h1>test</h1>
<p>foo</p>
<p>bar</p>
</body>
</html>
0111nobodyさん
04/07/23 00:29ID:TCCtsz0d指定したURLのファイルの更新時間を取得したいのですが
どうやって取得すればいいのでしょうか?
0113111
04/07/23 00:59ID:TCCtsz0dぐぐってHTTPの仕様と言う事はわかったのですがそれ以上の事は解りませんでした。
それをどうすれば取得できるのでしょうか?
0114nobodyさん
04/07/23 01:09ID:???0115111
04/07/23 01:31ID:TCCtsz0drequire LWP::UserAgent;
$ua = LWP::UserAgent->new;
$request = HTTP::Request->new('GET', 'http://google.co.jp/');
$response = $ua->request($request); # or
$response = $ua->request($request, '/tmp/sss'); # or
$response = $ua->request($request, \&callback, 4096);
sub callback { my($data, $response, $protocol) = @_;
print "$data";
}
0117111
04/07/23 01:39ID:TCCtsz0dHEADだと何も帰って来ないんです。
からっぽです。
0118nobodyさん
04/07/23 01:41ID:???http://www.studyinghttp.net/
http://member.nifty.ne.jp/hippo2000/perltips/LWP.html
■ このスレッドは過去ログ倉庫に格納されています