Perlコーディング初心者質問スレ Part 44
■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん
2005/10/17(月) 00:47:17ID:???【投稿する際の注意】
質問するときは内容をよく吟味してから投稿してください。
「コマンドの意味がわかんない」とかはマニュアル見ましょう。
回答者さんは何でも屋じゃありません。
1: 自分はこういう事がしたい。
2: それでこんな風にやってみたが・・・
3: こんなエラーが出て上手く行かなかった。
最低でも1と3が無いと誰も答えられないよ。
ソース貼る時は、全角スペースでインデント忘れずに。
良い回答は良い質問から。一緒に勉強しましょう。
過去ログやお勧めサイトは >>2-10
0081nobodyさん
2005/10/18(火) 22:27:43ID:???「変数宣言」がコメントになってないとか
あと、何がうまくいかないのか不明。
500エラーなのかファイルに保存されないのか、詳しく書くように。
008280
2005/10/18(火) 22:32:41ID:???すみません。
インターナルサーバエラーを起こして動かないという状況です。
ちなみに変数宣言は
my ($form, $com);
としています。
0083nobodyさん
2005/10/18(火) 22:41:45ID:???ヒント:Content-type(たぶん)
008479
2005/10/18(火) 23:10:34ID:???0086nobodyさん
2005/10/18(火) 23:42:22ID:???0089nobodyさん
2005/10/19(水) 00:52:35ID:???何に使われるのかが非常に気になるのだが・・・
0091nobodyさん
2005/10/19(水) 17:01:02ID:mMzWKjOm指定したディレクトリ内にある、ファイルとディレクトリの名前、
そしてそれらのパーミッションを取得して表示させるCGIを作成してます。
stat でファイルのパーミッションは上手く取得できるのですが、
ディレクトリのパーミッションは 000 が返ってきます。
どうやったらディレクトリのパーミッションも取得できますか?
該当部分の今のソースはこんな感じです。
$dir ="cgi-bin";
opendir(DIR, $dir);
while (defined($uhaha = readdir(DIR))) {
if ($uhaha ne '.' && $uhaha ne '..') {
@st = stat "$permis";
$per = substr((sprintf "%03o", $st[2]), -3);
print "$uha:$per<br>\n";
}
}
closedir(DIR);
0092nobodyさん
2005/10/19(水) 17:13:00ID:mMzWKjOmopendir(DIR, $dir);
while (defined($uhaha = readdir(DIR))) {
if ($uhaha ne '.' && $uhaha ne '..') {
@st = stat "$uhaha";
$per = substr((sprintf "%03o", $st[2]), -3);
print "$uhaha:$per<br>\n";
}
}
closedir(DIR);
0093nobodyさん
2005/10/19(水) 17:18:56ID:???こちらの環境ではちゃんと表示されるよ
問題は他のところにあると思う
関係ないけれど、
> $per = substr((sprintf "%03o", $st[2]), -3);
ここは
$per = sprintf "%03o", $st[2] & 0700;
の方が良いんじゃないかと思ったり
009493
2005/10/19(水) 17:20:55ID:???$per = sprintf "%03o", $st[2] & 0777;
0095nobodyさん
2005/10/19(水) 17:36:12ID:???パーミッションを000にすることは普通ないだろうから、
statに失敗している可能性があるな。
opendir(DIR, $dir);
while (defined($uhaha = readdir(DIR))) {
if ($uhaha ne '.' && $uhaha ne '..') {
@st = stat "$uhaha";
if (@st > 0) {
$per = substr((sprintf "%03o", $st[2]), -3);
print "$uhaha:$per<br>\n";
} else {
print "$uhaha:stat失敗($!)\n";
}
}
}
closedir(DIR);
とでもして試してみたらどうだろうか。
0096nobodyさん
2005/10/19(水) 17:57:17ID:???stat "$dir$uhaha"
じゃなかろうかカレントディレクトリでテストしちゃったから気づかなかった
009791
2005/10/19(水) 17:57:31ID:mMzWKjOmありがとうございます。
後述しますが、こちらの環境のせいかもしれません.....
あと、$per = sprintf "%03o", $st[2] & 0777; の方が何故良いのか、
パッと見てまだわからないので、後で調べてみます。
>>95
やってみました。
全部「stat失敗(No such file or directory)」でした。
そして、なんらかの原因でうまく情報を取得できていないみたいだったんで、
情報を取得したいディレクトリの中に、このスクリプトを放り込んで実行した所、
完璧に表示されました。
上位でも下位でも、階層が違うディレクトリを指定すると、
上手く情報が取得出来ないようです。
なんでだ...
009891
2005/10/19(水) 18:00:40ID:mMzWKjOm全て謎がとけましたw
その通りですね。
テンパってるとダメですね.....ありがとうございました!
0099nobodyさん
2005/10/19(水) 23:56:03ID:???0,yamada,A32,333
1,tanaka,B22,555
上記のようなCSVファイルから1行ずつ読み込んでハッシュに入れたいのですがどのように
すればいいのでしょうか。問題点がCSVの一行目をカンマごとにばらしたのをハッシュのキー名
にして2行目からをそれぞれの値として入れなくてはいけないのです。
モジュールも使えないのでよりどうしたらいいのかわかりません。
$filename="test.csv";
%arr2 = &COUNT($filename);
foreach $value (values %arr2) {
print "$value\n";
}
sub COUNT{
open (IN, $filename)or die "$!";
while(<IN>){
$buff = $_;
chomp($buff);
@buff = split(/,/, $buff);
%arr2 =();
$arr2[] = @buff[];
$arr2[] = @buff[];
$arr2[] = @buff[];
close IN;
return %arr2;
}
}
whileの前に先に一行だけ読み込んでキーを作ってしまうべき何でしょうか。
ずっと堂々巡りで悩んでしまいました。
0100nobodyさん
2005/10/20(木) 00:29:03ID:???>whileの前に先に一行だけ読み込んでキーを作ってしまうべき何でしょうか。
それが一番ラクだと思うけど。むしろ何故ソレを実行しないのかわからん。
0101nobodyさん
2005/10/20(木) 00:32:14ID:???@buff = split(/,/, $buff);
%arr2 =();
$arr2[] = @buff[];
$arr2[] = @buff[];
$arr2[] = @buff[];
の意味が分からん。俺の知識不足。つまり
@buff = split(/,/, $buff);
%arr2 =();
$arr2[0] = @buff[0];
$arr2[1] = @buff[1];
$arr2[2] = @buff[2];
ってことなの?
0102nobodyさん
2005/10/20(木) 00:36:48ID:???$arr2[0] = shift(@buff);
$arr2[1] = shift(@buff);
...
だろうな。そもそもハッシュ使いたいっぽいからこれでも違うけど。
てか今はどうしていいかわからなくなってる状態だと思われ。
0103nobodyさん
2005/10/20(木) 00:36:51ID:???これでいいのか分からんが。
count('test.csv' => \%data) or die 'Failed to count';
print "$_: ", join(' / ', @{$data{$_}}), "\n" for sort keys %data;
sub count {
-f (my $file = shift) or warn('No such file'), return;
open IN, '<' . $file or warn($!), return;
my $hash = shift;
my @key = <IN> =~ /\w+/g;
while (<IN>) {
chomp;
my $i = 0;
push @{ $hash->{$key[$i++]} }, $_ for split /,/;
}
close IN;
}
010499
2005/10/20(木) 00:47:28ID:???この次の段階としてCSVファイルの任意の部分だけを読み込み、書き換えよう
にしなくてはいけないので、できるだけ汎用性を持たせた関数を作るよう心がけるように
との事なので、悩んでいました。
配列のところはそのようにするつもりです。whileでまわして配列をハッシュに移すのに
途惑っていて流れが整理できなくなっていました。
家の環境ではすぐに試せないのですが皆さんいろいろアドバイスありがとうございます。
010699
2005/10/20(木) 01:20:15ID:???0107nobodyさん
2005/10/20(木) 01:46:11ID:???my @data;
open(IN, $file) or die $!;
(my $key = <IN>) =~ s/^#\s*|\n//g;
my @keys = split(/,/, $key);
for (<IN>) {
chomp;
local %_;
@_{@keys} = split(/,/);
push( @data, { %_ } );
}
close(IN);
---
結果、以下のように代入される。
@data = (
{ 'ID' => '0', 'NAME' => 'yamada', 'TEL' => '333', 'ADDRESS' => 'A32' },
{ 'ID' => '1', 'NAME' => 'tanaka', 'TEL' => '555', 'ADDRESS' => 'B22' }
);
アクセスは、
print $data[0]{NAME}; # yamada
print $data[1]{TEL}; # 555
0108nobodyさん
2005/10/20(木) 02:51:02ID:???と書いてあるのは分かってるが、あえてCPAN モジュール版を。CSVって、
カンマで区切ってるだけと思ってる人も多いけど、泥くさいフォーマットだよ。
use strict;
use warnings;
use IO::File;
use Text::CSV;
my $parser = Text::CSV->new();
my $in = IO::File->new('test.csv', 'r')
or die('test.csv: ' . $!);
(my $field_names_line = <$in>) =~ s/^#\s*//;
$parser->parse($field_names_line)
or die('field keys are not found');
my @field_names = $parser->fields();
my @list = ();
while (1) {
my $row = $parser->getline($in);
last unless 0 < @$row;
my %hash = ();
@hash{@field_names} = @$row;
push(@list, \%hash);
}
@list = (...>>107 と同じ内容...);
0109nobodyさん
2005/10/20(木) 17:31:51ID:jR9yJZEclinuxサーバでパスワードの変更の際(passwdコマンド)に、
推測されやすいと判断をした場合、再入力を求めるようにするプログラムをperlで作る事は可能でしょうか?
可能な場合はどのような設置をすればよいのでしょうか?
0111nobodyさん
2005/10/20(木) 19:53:12ID:???passwdコマンドにそのチェックをする機能を追加した
ようなものをperlで書いてもとのpasswdコマンドを
置き換えてしまうのが一番楽じゃないかと思われ。
0113nobodyさん
2005/10/20(木) 20:31:40ID:???可能。だが、その質問をしている時点で現在の>>109には敷居が高いだろう。
また、いくらシステム側で対処しても、
その手の脆弱性の根本部分はユーザーのセキュリティー意識にある。
「推測されにくいパスワードを使う」ことと教えてあげる方がよい。
0114nobodyさん
2005/10/20(木) 20:45:15ID:jR9yJZEc例えば、4桁未満は駄目とか、数字のみは駄目等です
>>112
それはpasswdコマンドを書き換えるのはどこを操作すればよいのでしょうか?
また、perlで無くてもっと簡単にかける方法は無いものでしょうか
(どのファイルをどのように書き換えたらよいか等)
>>113
全くその通りなんですけど、自分の今後の為にと思いまして。
0115110
2005/10/20(木) 20:59:52ID:???> 例えば、4桁未満は駄目とか、数字のみは駄目等です
これって既に、生の passwd コマンドが実装している機能では?
同じ機能を Perl で再実装したいって思うのは自由だけどね。
とりあえず、passwd のマニュアルページとソースコードを読んでみることをお勧めします。
0116nobodyさん
2005/10/20(木) 21:03:16ID:???0117nobodyさん
2005/10/20(木) 22:05:06ID:???その質問レベルを見る限りではpasswdコマンドをどうこうしようとか
思う前に基本を勉強した方がよさそうだな...
0118nobodyさん
2005/10/20(木) 22:29:24ID:???同感
rootで動くためにはパーミッションに細工した上で実行時にIDを変えてやる必要があるが、
この方法を知らないようなレベルで作ろうとしてもセキュリティホールを作ってしまう危険の方が高いと思う…
011999
2005/10/21(金) 00:50:33ID:???4つめのキーの部分が出てこないのはどうしてでしょうか?
少しソースを変えていますが、
スカラーで確かめてみるとハッシュのキーは4つ確保されているのにADDRESSの項目だけが
表示されません。よろしくお願いします。
0121119
2005/10/21(金) 01:28:01ID:???print $data[3]->{ID};
print $data[3]->{NAME};
print $data[3]->{TEL};
print $data[3]->{ADDRESS};
のようにやっています。
4つ目のキーがうまくついていないのでしょうか。
0123nobodyさん
2005/10/21(金) 01:41:21ID:???http://www.kt.rim.or.jp/%7Ekbk/perl5.005/perlfaq8.html#How_do_I_ask_the_user_for_a_pass
>>119-122
改行コードが原因なら
- (my $key = <IN>) =~ s/^#\s*|\n//g;
+ (my $key = <IN>) =~ s/^#\s*|\s*\z//g;
ASCII 互換なら文字コードは関係無い。
0125nobodyさん
2005/10/21(金) 01:59:13ID:???改行コードかも知れません。最初の読み込みではずしてしまっているみたいなので。
いろいろ試してみます。
これとは別なcsvなのですがこちらの値は"yamada" のように"とタブでで区切っていていてこれを
=~ s/" //g;
ではずそうといろいろいじてるうちになってしまったみたいです。
こちらは今何とか自分で試行錯誤しています。
ありがとうございました。
0126nobodyさん
2005/10/21(金) 02:39:27ID:???修正サンクス。
あと、細かいけどこっちの方がよかった。展開が減るので。
- push( @data, { %_ } );
+ push( @data, \%_ );
>>125
改行の取り扱い不足でした。sorry。
> これとは別なcsvなのですがこちらの値は"yamada" のように"とタブでで区切っていていてこれを
> =~ s/" //g;
tab 文字も \s でマッチするので
s/"\s*//g;
がおすすめ。
0127nobodyさん
2005/10/21(金) 04:21:29ID:???\%_ にするんだったら local %_; じゃないほうがよいのでわ。
Excelなら、クオーテーションは Perlメモ の CSV の項を読むといいと思う。
0128nobodyさん
2005/10/21(金) 04:30:43ID:???local $_ は単に global な %_ を壊さないようにしている
のだけど(このコードだと不要だけど)、
それ以外にデメリットってあります?
0129nobodyさん
2005/10/21(金) 04:32:11ID:???0130128
2005/10/21(金) 04:40:25ID:???値を上書きしまいますね。
まぎらわしいので my 変数の方がいいのでは、ってことですね。
0131nobodyさん
2005/10/21(金) 15:03:57ID:???0132nobodyさん
2005/10/21(金) 15:24:58ID:???0133nobodyさん
2005/10/21(金) 17:35:12ID:???アンケイートをつくっているのですが、
【hoge.html1】
<FORM ACTION="hoge1.cgi" METHOD="post">→送信→log1
【hoge.html2】
<FORM ACTION="hoge2.cgi" METHOD="post">→送信→log2
↓
【hoge.html1】
<FORM ACTION="hoge.cgi" METHOD="post">→次へ→この分をまずlog3へ
【hoge.html2】
<FORM ACTION="hoge.cgi" METHOD="post">→送信→log3→おわり
てしたいんだけど、(2つのフォームの内容繋げて一気に送ってlog残したい)
どんなソース書けばいいですか?
0134nobodyさん
2005/10/21(金) 17:38:17ID:???javascript でも勉強したら?
0135nobodyさん
2005/10/21(金) 20:29:51ID:???一意のIDをcookieか何かで発行する、いわゆる「セッション」を使うのが普通だが、
htmlで、と言われると困る。mod_rewriteでも使って誤魔化すか。
で、言語は何よ?
0136nobodyさん
2005/10/21(金) 20:33:21ID:???0137nobodyさん
2005/10/21(金) 20:49:56ID:???=~s/\Eアンケ(イ|ー)ト\Q/アンケ$1ト/g;
0138nobodyさん
2005/10/21(金) 20:55:34ID:???0139nobodyさん
2005/10/21(金) 21:01:40ID:???>>133
元のhoge1.cgiとhoge2.cgiはコピーして2つにしただけでしょ?
1のクエリはすぐに処理せず
2のフォームのhiddenにでも入れておいたら?
0140nobodyさん
2005/10/21(金) 21:03:44ID:???0141nobodyさん
2005/10/22(土) 15:11:53ID:m3HcshJvフォームで入力後、WEBに以下のような感じでフィルに書き出すんですが
if(open(FILE,">>hogehoge.log")) {
$record .= $in{'name'}."\t";
$record .= $in{'kana'}."\t";
jcode::convert(\$record,'sjis');
print OFILE $record;
close(OFILE);
name が空白でないかを書き込み前にチェックしたいのですが、うまく動きません。
以下の記述を入れるかと思いますが、どの行に入れたら動作するでしょう?
if ($FORM{'name'} eq "") { &errexit("お名前は必ず入力してください"); }
以下のエラーが出ます。
Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator, [no address given] and inform them of the time the error occurred, and anything you might have done that may have caused the error.
More information about this error may be available in the server error log.
よろしくお願いします。<(_ _)>
0143nobodyさん
2005/10/22(土) 15:27:16ID:G1Q0Ugqh0144nobodyさん
2005/10/22(土) 15:33:15ID:m3HcshJvエラー行が表示されました。ありがとうございます。<(_ _)>
>>143
OFILE と FILE の違いがよくわかっておりません。 ご教授下さい <(_ _)>
0145nobodyさん
2005/10/22(土) 15:35:19ID:m3HcshJvUndefined subroutine &main::errexit called at /virtual/hogehoge.cgi line 18.
追記した↓この行があかんみたいです
if ($FORM{'name'} eq "") { &errexit("お名前は必ず入力してください"); }
0146nobodyさん
2005/10/22(土) 15:43:00ID:???知識レベルとしては、Cで普通にプログラムは書けますが、
perlは本当に始めたばかりです。
<質問事項>
基本の基本ということで以下のコードを書いたのですが
画面上に何も表示されません。(エラー等も表示されません)
printは画面(標準出力)に文字列を表示させると思っています。
コードもしくは認識に誤りがあるのでしょうか?
<コード>
■test.cgi
#!/usr/bin/perl
print "Program start\n";
print "Program end\n";
■実行方法
./test.cgi
■ファイルの属性
-rwxrwxrwx 1 root www 129 10月 22 15:37 test.cgi
■whichの結果
which perl
/usr/bin/perl
0147nobodyさん
2005/10/22(土) 15:54:11ID:???・・・
0152nobodyさん
2005/10/22(土) 16:04:32ID:m3HcshJvご指導ありがとうございます。
文字列が入ってても以下のメッセージが表示されます。
「お名前は必ず入力してください。」
0154nobodyさん
2005/10/22(土) 16:14:10ID:m3HcshJv#!/usr/bin/perl
use CGI::Carp qw(fatalsToBrowser);
sub errexit { print "\n", @_; exit; }
require "cgi-lib.pl";
require "jcode.pl";
if ($FORM{'name'} eq "") { &errexit("お名前は必ず入力してください。"); }
if(open(OFILE,">>hogehoge.log")) {
$record .= $in{'name'}."\t";
print OFILE $record;
close(OFILE);
#フォームの表示
print "Content-type: text/html\n\n";
print qq!
<HTML>
<HEAD>
0155nobodyさん
2005/10/22(土) 16:17:36ID:JX8EwRu8「AAA AAAA」と「BBBBBBB」というデータを保存する際にスペースで区切ったために
「AAA\ AAAA BBBBBBB」のようにデータ上のスペースの前には\を置いて保存されています、
またデータ上の\は\\で保存されています。
これを読み出すための簡約化された手順がありましたら教えてください。
とりあえずデータ上で9文字目が区切りであることを検出できればいいです。
それとも、フォーマットについてもっとこうするべきだというものありましたら
いまからでも変更の余地がありますので提案お願いします。
0156nobodyさん
2005/10/22(土) 16:20:06ID:m3HcshJvif ($FORM{'name'} eq "") { &errexit("お名前は必ず入力してください。"); }
↑この行を省くと動作するのですが、空白でも post してしまいますので。
0157nobodyさん
2005/10/22(土) 16:22:39ID:???固定長なら \ でエスケープする必要ないんじゃ?
0159nobodyさん
2005/10/22(土) 16:34:17ID:m3HcshJv<HTML>以下のフォームにて取得してます。
<FORM ACTION="hogehoge1.cgi" METHOD="post" name="FORM" id="FORM">
<td colspan="2" nowrap><font size="3">ご氏名</font></td>
<td height="25"><input type="text" name="name" style="ime-mode: auto;" size="30">
</td> </tr>
0161nobodyさん
2005/10/22(土) 16:41:24ID:m3HcshJvFORM ACTION で name に入力された文字が代入されて
$record .= $in{'name'}."\t";
のところで タブ入りで record に渡されて
hogehoge.log ファイルに書き込むのと違うのですか?
0162nobodyさん
2005/10/22(土) 16:44:35ID:JX8EwRu89文字の固定長ではありません。
サンプルに対して取得したいデータが9であるという、あくまでも例です。
やはり自分で1文字ずつ検証して作るしかないでしょうか?
0163nobodyさん
2005/10/22(土) 16:47:54ID:???えーっとだ。
>>152でHTMLから送信してもエラーが出ちゃうと言う問題だろ?
書き込むとかどうでもよい。
受け取りができてないのよ。
cgi-lib.pl使ってるみたいだから↓読んで。
http://www.futomi.com/lecture/form/cgilib.html
0165nobodyさん
2005/10/22(土) 17:05:01ID:m3HcshJv以下の感じでよろしいんでしょうか?
my %input;
&ReadParse(\%input);
$YourName = $input{'name'};
if ($FORM{'YourName'} eq "") { &errexit("お名前は必ず入力してください。"); }
0168nobodyさん
2005/10/22(土) 17:09:47ID:???違う。
my %input;
&ReadParse(\%input);
if ($input{'name'} eq "") { &errexit("お名前は必ず入力してください。"); }
--以下保存処理
あと、試してから聞きなさい。
0169nobodyさん
2005/10/22(土) 17:25:59ID:???0170nobodyさん
2005/10/22(土) 17:30:16ID:m3HcshJv入力文字があっても 以下のメッセが表示されます。(・_・、)
"お名前は必ず入力してください。"
0171nobodyさん
2005/10/22(土) 17:38:30ID:???変数に何が入ってるかわからんのなら、printしてみようね。
あと、めんどいからどっかにCGIプログラムとHTMLのソースうpしる。
0172nobodyさん
2005/10/22(土) 17:47:29ID:???0173nobodyさん
2005/10/22(土) 18:02:37ID:m3HcshJvhttp://other.free-uploader.com/up/
hoge_1.cgi です。
0175nobodyさん
2005/10/22(土) 18:14:20ID:m3HcshJvたびたび、すいません。
0123
0176nobodyさん
2005/10/22(土) 18:18:44ID:???if (!$in{'name'}) { &errexit("お名前は必ず入力してください。"); }
0177nobodyさん
2005/10/22(土) 18:19:41ID:???0178nobodyさん
2005/10/22(土) 18:27:02ID:vPMo38wNhttp://allabout.co.jp/career/cgiperl/closeup/CU20040805A/index4.htm
0180nobodyさん
2005/10/22(土) 18:36:12ID:m3HcshJvひとつを消したんですが、結果は
>>170 と同じです。 (×_×)
■ このスレッドは過去ログ倉庫に格納されています