Perlについての質問箱 30箱目
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2007/03/14(水) 22:54:12"There's more than one way to do it" ということで、Perlの奥深さについて皆で語り合い、追求してまいりましょう。
CGIについての質問は板違いです。WEBプログラミング板でどうぞ。
CGIとPerlの区別がつかない人もWEBプログラミング板に行ってください。
(WEBプログラミング板 http://pc8.2ch.net/php/ )
CGIの質問は答えがPerlと全然関係ない話に帰着する場合が多かったりするのでWEBプログラミング板に行って聞いたほうが得ですよ。
このスレでは(CGI以外の)純粋にPerlのみに関係する質問を取り扱っていこうと思います。
スレ違いの質問にはスルーか、速やかな誘導をお願いします。
http://www.perl.org/get.html
● 2006/12/21現在の最新版: 5.8.8
● 2006/12/21現在の開発版: 5.9.3
前スレ
Perlについての質問箱 29箱目
http://pc11.2ch.net/test/read.cgi/tech/1166708139/
リンク集は>>2-3
過去スレは>>4
0330デフォルトの名無しさん
2007/04/22(日) 16:35:51レスありがとうございます。
>あえて /usr/bin/perl ではなく /usr/local/bin/perl を使いたいわけね?
はい。ソースコードからインストールしたらそこにインストールされたので、
/usr/local/bin/perl を使っています。
>で、実際に使ってる(環境変数 PATH で優先的に参照される)のは /usr/bin/perl ではなく、
>/usr/local/bin/perl ってことに間違いはない?
間違いないはずです。
which perl で確認しました。
CPAN.pm の該当箇所をみると、
$CPAN::META->has_inst("Compress::Zlib") で判定した後に、
Compress::Zlib::gzopen を呼び出していました。
そこで gopen がないとなる理由がよく分かりません。
> >で、実際に使ってる(環境変数 PATH で優先的に参照される)のは /usr/bin/perl ではなく、
> >/usr/local/bin/perl ってことに間違いはない?
> 間違いないはずです。
> which perl で確認しました。
$env
してみると判るけれども標準ではpathが通っていないと思うですです。
PATH=/bin:/sbin:/usr/bin:/usr/sbin
@MacOSX 10.4.9
もっぺん確認してみよう♪
♯tu-ka未だに5.8.6のままなんだよなぁ。。。(´・ω・`)
$ perl -v
This is perl, v5.8.6 built for darwin-thread-multi-2level
(with 3 registered patches, see perl -V for more detail)
0332デフォルトの名無しさん
2007/04/22(日) 17:55:38レスありがとうございます。
$env
で確認してみましたが、先頭に/usr/local/binがありました。
PATH=/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin
こうなるように、以前./bash_profile に追加しました。
となると、原因は不明でしょうか?
インストールの仕方が悪かったのかなあ。
0333デフォルトの名無しさん
2007/04/22(日) 20:53:01手動で入れろ。
0334デフォルトの名無しさん
2007/04/22(日) 21:21:50PDFファイルのすべてを把握するのが目的です。
CPANをみたところ、PDFのテキストや書誌情報を抽出したりするためのAPIは用意されてる
のですが、もっと低レベルなパーサーがないようです。。
各種トークンが出現するたびにイベントを起動するような奴がほしいんですが。
HTML::ParserのPDF版でPDF::Parserみたいな感じの奴です。
0335デフォルトの名無しさん
2007/04/22(日) 23:26:59UTF-8でURIエスケープされた文字列を、アンエスケープするPerlの処理でけつまづいてます。
元の文字列をURIエスケープした文字列がサーバ側まで来ているのは確認しました。
「質問」→「%E8%B3%AA%E5%95%8F」だとか、「ü」→「%C3%BC」だとか。
これを
$utf8str =~ s/%([a-f\d]{2}/pack('H2',$1)/egi;
しても、正しくアンエスケープされない(文字化けする)のです。
UTF-8が可変バイトなのが曲者なのでしょうか。。。
ググった先(ttp://oshiete1.goo.ne.jp/kotaeru.php3?q=1644542)の
$utf8str =~ s/%(e[a-f\d])%([a-f\d]{2})%([a-f\d]{2}/pack('H2',$1).pack('H2',$2).pack('H2',$3)/egi;
してもやはりだめでした。
0336デフォルトの名無しさん
2007/04/22(日) 23:56:33むあじっすか。
0337デフォルトの名無しさん
2007/04/22(日) 23:59:22use Encode qw/from_to/;
my $str = '%E8%B3%AA%E5%95%8F'; # utf8の'質問'をエスケープ
(my $dec = $str) =~ s/%([a-f\d]{2})/pack 'H2', $1/egi;
from_to($dec, 'utf8', 'cp932'); # Winのコマンドプロンプトで表示するのでcp932にしてる
print $dec;
とりあえずこれで動いてるけど? ブラウザに出してるんなら、Shift_JISって解釈されてるとかじゃない??
0338デフォルトの名無しさん
2007/04/23(月) 00:01:31> $utf8str =~ s/%([a-f\d]{2}/pack('H2',$1)/egi;
$1のための括弧が閉じられてません。
あとは、UTF-8に対応したEditorで開いてないとかでしょうか。
上の式で正しくアンエスケープされました。
0339デフォルトの名無しさん
2007/04/23(月) 00:35:06>>337さんのスクリプトを実行したところ、文字化けしませんでした。
また、from_toする前でも、ファイルにリダイレクトして、
そのファイルをエディタで開いても同様に文字化けしていませんでした。
しかし、サーバに持って行ってブラウザに結果を出すと文字化けしてしまいます。
エディタはUTF-8に対応していて、Perlスクリプトもutf-8で保存して、
use utf8; use open ":utf8"; use open ":std";して、
print "Content-type: text/html; charset=utf-8\n\n";
いるのですが、
>>337さんのものでprint $dec;でもprint $str;でも駄目(文字化け)でした。
環境はWin XP SP2 + IE7、[表示]-[エンコード]でもUTF-8であることを確認しているのですが。。
。
度々で申し訳ないのですが、他に何か怪しい箇所がありますでしょうか?
0340デフォルトの名無しさん
2007/04/23(月) 00:49:03my $str = '%E8%B3%AA%E5%95%8F';
(my $dec = $str) =~ s/%([a-f\d]{2})/pack 'H2', $1/egi;
print "Content-Type: text/plainl; charset=utf-8\n\n";
print $dec;
__END__
とりあえず手元だとこれで動いてる。まずは問題の発生する最小限のコードまで切り詰めてみ?
0341337
2007/04/23(月) 01:17:20use open ":std";が余計でした(よく分からないのに「おまじない」で書くのは駄目でしたね)。
問題のスクリプトから上記を除いて、かつ、
自分で作って読んでいるモジュールからも上記を除きました。
本当にありがとうございます!
0342デフォルトの名無しさん
2007/04/23(月) 01:18:56標準入出力を使わないなら、use open ":std";等は確かに不要でした。
0343335
2007/04/23(月) 03:15:36use open ":std";を外せばアンエスケープで文字化けしないものの、
今度は後続処理でUTF-8な文字を処理できないという問題がありました。
結局、以下のサイトを参照して、
ttp://naoya.dyndns.org/~naoya/mt/archives/000611.html
use open ":std";は残したままで、アンエスケープ処理の後に
utf8::decode($str);でUTF8フラグを落とせば、
スクリプトへのUTF-8文字列の受け渡しも、後続処理も、うまく行きました。
夜更けにお答えくださって、本当にどうもありがとうございました。
これで安心して眠れそうです。
0344デフォルトの名無しさん
2007/04/23(月) 18:08:16http://mixi.jp/view_bbs.pl?id=17607679&comm_id=1401396
Perlに関すること、cgiに関すること
なんでも質問できるコーナーです(たとえばApacheとかでもOKとします!)
(Web系であればOK)
ルール:
Google検索で調べてわかるようなことでも質問してもOKです
(初心者のうちは、どの情報を取捨選択したらイイのかわからないと思うので)
回答してくださるかたは、暖かく質問者を迎えてやってください
o(^^o) (o^^)o
0345デフォルトの名無しさん
2007/04/23(月) 18:19:57コミュニティのタイトルとか説明文が凄く気になって仕方が無い。
PERL言語 CGI言語
コミュニティの説明
perl言語 cgi言語のコミュニティです
だそうです。。。
0347デフォルトの名無しさん
2007/04/24(火) 04:11:190348デフォルトの名無しさん
2007/04/24(火) 08:17:440349デフォルトの名無しさん
2007/04/24(火) 10:36:140350デフォルトの名無しさん
2007/04/24(火) 22:51:58最後に管理者がキレるに1票。
0351デフォルトの名無しさん
2007/04/25(水) 02:27:300352デフォルトの名無しさん
2007/04/25(水) 11:12:27「ググれカス」だの「マニュアル嫁」みたいな回答しか
返ってこなかったので、管理人にやさしく教えてくれる
ところが欲しかったんじゃないの?
0353デフォルトの名無しさん
2007/04/25(水) 12:06:40もちろんそうでしょ。
そうじゃなきゃルール書きの冒頭が「Google検索で調べて
わかるようなことでも」で始まるわけないっすよ。
0354デフォルトの名無しさん
2007/04/25(水) 12:33:510355デフォルトの名無しさん
2007/04/25(水) 17:38:480356デフォルトの名無しさん
2007/04/25(水) 19:00:43役に立たないものはない。
川に流してしまいたい。
0358デフォルトの名無しさん
2007/04/25(水) 21:32:050359デフォルトの名無しさん
2007/04/25(水) 22:08:090360デフォルトの名無しさん
2007/04/25(水) 23:13:460361デフォルトの名無しさん
2007/04/25(水) 23:27:060362デフォルトの名無しさん
2007/04/26(木) 09:20:12(===○=)/ センセー
__ / ⇔ / 話しについてけませーん
\⊂ノ ̄ ̄ ̄\
||ヽ|| ̄ ̄ ̄ ̄||
...|| ̄ ̄ ̄ ̄||
0363デフォルトの名無しさん
2007/04/26(木) 22:17:39CGI言語と来たか・・・。
本当に作ってしまって混乱させるというのはどうか?
もちろんその言語はクライアントマシンの限られた
中でしか使えず、 Web の CGI になんて使えないのだ。
0364デフォルトの名無しさん
2007/04/26(木) 22:18:420365デフォルトの名無しさん
2007/04/26(木) 23:07:100366デフォルトの名無しさん
2007/04/26(木) 23:15:11池袋で乗車してきた女の子がハロプロエッグの子とかたかまりこ
0367デフォルトの名無しさん
2007/04/27(金) 11:39:270368デフォルトの名無しさん
2007/04/27(金) 11:57:030369デフォルトの名無しさん
2007/04/27(金) 15:28:360370デフォルトの名無しさん
2007/04/27(金) 15:34:310371デフォルトの名無しさん
2007/04/27(金) 17:29:180372デフォルトの名無しさん
2007/04/27(金) 18:13:20どうすればよろしいでしょうか?例えば、
dir c:\trash
の結果を取り込もうとしても、次のスクリプトではうまくいきません。
$files = `dir c:\\trash`;
print "The files are $files\n";
0373デフォルトの名無しさん
2007/04/27(金) 18:43:530374デフォルトの名無しさん
2007/04/27(金) 18:53:55手元だとそれでうまくいってるけど。
0375372
2007/04/27(金) 20:04:12すみません。書き忘れていました。>>10にある先頭の5行を入れていました。
use utf8;
use open IO => ":encoding(cp932)";
binmode STDIN => ":encoding(cp932)";
binmode STDOUT => ":encoding(cp932)";
binmode STDERR => ":encoding(cp932)";
「use open IO => ":encoding(cp932)"; 」の行を削除して
次のように修正すると動きました。
use Encode;
$orgfiles = `dir c:\\trash`;
$files = decode('cp932', $orgfiles);
print "The files are $files\n";
0376デフォルトの名無しさん
2007/04/27(金) 21:23:44例によって cmd.exe /c dir ... じゃない?
0377デフォルトの名無しさん
2007/04/27(金) 21:24:530378デフォルトの名無しさん
2007/04/27(金) 21:35:08記号が多いから、とか?
0379デフォルトの名無しさん
2007/04/27(金) 22:21:10うんにゃ、LWPのUAがはじかれる件でしょ?
0380デフォルトの名無しさん
2007/04/27(金) 22:23:19Perlで書かれたボットの多くがLWPのデフォルトUser-Agentをそのまま名乗って
おり、403を食らうようになった。当然だがUAを変えれば通れる。
0381デフォルトの名無しさん
2007/04/27(金) 22:24:27今回のそれとは違うよな。
0382デフォルトの名無しさん
2007/04/27(金) 22:30:29そう責めるな
0383デフォルトの名無しさん
2007/04/28(土) 00:19:39それとも使う奴だけ手動でアップデートさせるしか方法ない?
0384デフォルトの名無しさん
2007/04/28(土) 00:39:19cpanシェルでupgrade
0385378
2007/04/28(土) 01:18:470386デフォルトの名無しさん
2007/04/28(土) 03:22:170387デフォルトの名無しさん
2007/04/28(土) 05:09:490388デフォルトの名無しさん
2007/04/28(土) 17:56:47Pealのeqとかみたいにさ
0389デフォルトの名無しさん
2007/04/28(土) 19:26:07なったと言っても数年前からだよ。
今頃騒いでるやつらはアンテナが低すぎると思ったのだった。
0390デフォルトの名無しさん
2007/04/29(日) 01:57:47char len1;
char word1[len1];
char len2;
char word2[len1];
char len3;
char word3[len1];
}
みたいな構造の可変長のバイナリなデータがあるんですが、
これをperlで綺麗でかっこよく展開する方法ってないですか?
今は下のようなことをしてるのですが、なんか見辛いし汚いので…
$data = "\4ABCD\3EFG\7HIJKLMN";
($len1,$data) = unpack("Ca*",$data);
($word1,$data) = unpack("a${len1}a*",$data);
($len2,$data) = unpack("Ca*",$data);
($word2,$data) = unpack("a${len2}a*",$data);
($len3,$data) = unpack("Ca*",$data);
($word3,$data) = unpack("a${len3}a*",$data);
print "$word1\n$word2\n$word3\n";
0391デフォルトの名無しさん
2007/04/29(日) 03:40:490392デフォルトの名無しさん
2007/04/29(日) 04:06:37perldoc -f pack して目を皿のようにして熟読せい。
The "/" template character allows packing and unpacking
of strings where the packed structure contains a byte
count followed by the string itself. You write
*length-item*"/"*string-item*.
0393デフォルトの名無しさん
2007/04/29(日) 05:12:56あああああ、そんなテンプレートがあったんですね。
日本語の5.6ベースのman見てたので気づきませんでした…
ありがとうございます。
0394デフォルトの名無しさん
2007/04/30(月) 02:59:39あ、すまん。
5.6からの拡張だと思ってたが、違ったか(393には問題ないみたいでよかった)。
0395デフォルトの名無しさん
2007/05/01(火) 17:38:05「置換する」「置換しない」(飛ばす)「残り全て置換」「キャンセル」という
処理を行うにあたって、見つけた文字列を置換せずに飛ばして次を置換する
方法が思いつきません。置換しないテキストは適当な文字列に置換しておいて
最後に戻すという方法も考えたのですが、あまりスマートではないと思いまし
た。何かよい方法があったら、お知恵をお貸しください。
while($text =~ /($regexp)/) {
if($all == 0) {
$before = $1;
$after = $1;
$after =~ s/$regexp/$replace/m;
print "置換前:\n$before\n置換後:\n$after\n";
do {
print "置換する? [y]es [n]o [a]残り全て [g]キャンセル ";
$key = <STDIN>;
chomp($key);
} while ($key ne "y" and $key ne "n" and $key ne "a" and $key ne "g");
if($key eq "y"){
$text =~ s/$regexp/$replace/m;
}elsif($key eq "n"){
# ここをどうする?
}elsif($key eq "a"){
$text =~ s/$regexp/$replace/gm;
$all = 1;
}else{ exit; }
}elsif($all == 1) {
$text =~ s/$regexp/$replace/gm;
}
}
0396395
2007/05/01(火) 17:39:43置換後の文字列です。
0397デフォルトの名無しさん
2007/05/01(火) 17:51:02ヒント: posと\G
perl -e '$x = "aaaaaa"; pos($x) = 2; $x =~ s/\Ga/x/; print $x,"\n";'
aaxaaa
0398395
2007/05/01(火) 21:09:08$p = 0;
while($text =~ /\G(?:.*\n)*?.*?($regexp)/gm) {
$p = pos($text) - length($1);
pos($text) = $p;
if($all == 0) {
$before = $1;
$after = $1;
$after =~ s/$regexp/$replace/m;
print "置換前:\n$before\n置換後:\n$after\n";
do {
print "置換する? [y]es [n]o [a]残り全て [g]キャンセル ";
$key = <STDIN>; chomp($key);
} while ($key ne "y" and $key ne "n" and $key ne "a" and $key ne "g");
if($key eq "y"){
$text =~ s/\G$regexp/$replace/m;
pos($text) = $p + length($after);
}elsif($key eq "n"){
pos($text) = $p + length($before);
}elsif($key eq "a"){
$text =~ s/\G$regexp/$replace/gm;
$all = 1;
}else{
exit;
}
}elsif($all == 1) {
$text =~ s/\G$regexp/$replace/gm;
}
}
0399デフォルトの名無しさん
2007/05/01(火) 21:31:38最後の全置換は絶対うまくいかんだろ
0400デフォルトの名無しさん
2007/05/01(火) 22:01:180401395
2007/05/01(火) 22:02:38と、置換される文字列に改行が含まれている際に、オプション"g"をつけても
複数置換してくれなくなってしまうのですが、どうすればいいんでしょうか。
perl -e '$text = "a\na\na"; $text =~ s/\Ga/b/gm; print "$text\n";'
結果:
b
a
a
perl -e '$text = "aaa"; $text =~ s/\Ga/b/gm; print "$text\n";'
結果:
bbb
perl -e '$text = "a\na\na"; $text =~ s/a/b/gm; print "$text\n";'
結果:
b
b
b
0402デフォルトの名無しさん
2007/05/01(火) 22:23:56あとを置換しながらposを保持することはできないのでコピーを作ることを考えてみては
自分ならこう書く
my $replaced_text;
pos $text = 0;
while (pos $text < length $text) {
if ($text =~ m/\G $regexp/gcsx) {
# ここで入力による分岐処理を行う
}
elsif ($text =~ m/\G(.+?) (?=$regexp)/gcsx) {
$replaced_text .= $1;
}
else {
$text =~ m/\G (.*)/gcsx;
$replaced_text .= $1;
}
0403デフォルトの名無しさん
2007/05/01(火) 22:28:17my $mode;
$text =~ s{($regexp)}{
my $r;
if (!defined $mode) {
my $key;
do {
print "置換する? [y]es [n]o [a]残り全て [g]キャンセル ";
$key = <STDIN>;
chomp($key);
} while ( $key ne "y"
and $key ne "n"
and $key ne "a"
and $key ne "g" );
if ($key eq 'y') {
$r = $replace;
} elsif ($key eq 'n') {
$r = $1;
} elsif ($key eq 'a') {
$mode = 'a';
} else {
$mode = 'g';
}
}
if ($mode eq 'a') {
$r = $replace;
} elsif ($mode eq 'g') {
$r = $1;
}
$r;
}gme;
0404395
2007/05/01(火) 23:34:11おお、これはすごい、正規表現でループができるんですね。
>>403の方法できれいなスクリプトになりました。ありがとうございます。
0405デフォルトの名無しさん
2007/05/02(水) 03:13:40インストールするごとに[1]とか[2]とか増えるのはなんなんでしょうか?
0406デフォルトの名無しさん
2007/05/02(水) 03:44:02現在実行したコマンドを識別するIDみたいなもの。
何に使ってるかまでは見てないけど。
ちなみに↓とやるとIDを変えてしまうこともできる。特に意味はない。
cpan[1]> ! $CPAN::CurrentCommandId = 100;
0407デフォルトの名無しさん
2007/05/02(水) 05:56:50レスありがとうございます。
そうなんですか。
なんか Bundle::CPAN をインストールしてからそうなったような気がしたので、
間違えたかと思いました。
そのような情報ってどこで得ているのでしょうか?
0408デフォルトの名無しさん
2007/05/02(水) 09:35:320409デフォルトの名無しさん
2007/05/02(水) 14:03:43知らないけど、ヒストリ用では?
よくUNIX用のシェルであるんだけど、 ! の直後にその番号入れて
実行するとその番号のコマンドが動くんだよ。全く同じなら再入力
する必要がないの。(更に後ろに :s/// のようなのを付けて文字列
置換できたりもする。 !30:s/aa/bb/ みたいな。全てのシェルが
同じこと出来るかどうかは知らないが)。
0410デフォルトの名無しさん
2007/05/02(水) 21:18:490411デフォルトの名無しさん
2007/05/02(水) 21:20:370412デフォルトの名無しさん
2007/05/03(木) 06:35:392つのファイル a.txt と b.txt を比較して、条件にあった行を抽出、出力するスクリプトを作りたいのです。
具体的には、
[a.txt]
ID, field1, field2
1, 5.8, 7.3
2, 6.3, 8.2
3, 3.2, 4.1
4, 4.8, 4.0
5, 8.3, 10.2
[b.txt]
ID, field1, field2
1, 6.8, 7.7
3, 4.3, 5.5
4, 5.9, 4.9
というファイルがあったとき、b.txt のIDに数値が存在する行だけを a.txt から抽出して a2.txt として保存したいのです。
[a2.txt]
ID, field1, field2
1, 5.8, 7.3
3, 3.2, 4.1
4, 4.8, 4.0
と言った具合にです。よろしくお願いします。
0413デフォルトの名無しさん
2007/05/03(木) 07:47:00use strict;
use warnings;
open my $a, '<', 'a.txt' or die;
open my $b, '<', 'b.txt' or die;
my %ids = map { $_ => 1 } map { (split /,/)[0] } <$b>;
while (<$a>) {
my $id = (split /,/)[0];
print if $ids{$id};
}
0414412
2007/05/03(木) 08:00:05早速のレス、ありがとうございます。助かりました。
こんなに簡単にできちゃうんですね。しかし、私にはスクリプトの内容は不明...。解読して勉強させていただきます。
0415デフォルトの名無しさん
2007/05/03(木) 13:36:22sub func {
my $file = shift(@_);
my $input = IO::File->new($file,"r") or die;
ごにょごにょ
・
・
}
$filename = (ディレクトリからファイルネームをとるロジック);
&func($filename);
みたいに書くと、一番最初にいきなりファイルオープンのエラーが出ます。
その後、ファイルネームをとるロジックが走ってる模様…。
何故か解らないのですが原因解りますでしょうか。
0416デフォルトの名無しさん
2007/05/03(木) 13:48:01原因はわかりますよ。
あんたが、そう動くようにプログラムを作ったから。
0418415
2007/05/03(木) 14:26:25サブルーチンが先に実行される事なんてあるのか…?
0419デフォルトの名無しさん
2007/05/03(木) 14:50:10まあエラーメッセージでも貼ってみ
0421デフォルトの名無しさん
2007/05/03(木) 15:08:03訳したりせずにそのまま貼れ
0422415
2007/05/03(木) 15:16:54だけです。
CentOS4.4、perl5.8.5です。
0423415
2007/05/03(木) 15:30:01>>422さん、親身になってくれてありがとうございます。
くだらないミスで申し訳ありません。
本当にすみませんでした。
0424デフォルトの名無しさん
2007/05/03(木) 15:40:40s/422/421/g;
0425デフォルトの名無しさん
2007/05/03(木) 15:47:38my $fp_in = IO::File->new($filename, "<") or die qq(cannot open '$filename': $!);
0427デフォルトの名無しさん
2007/05/05(土) 14:17:500428デフォルトの名無しさん
2007/05/05(土) 14:26:54略じゃないよ。
噛み切るとかそんな感じ。
0429デフォルトの名無しさん
2007/05/05(土) 14:41:24■ このスレッドは過去ログ倉庫に格納されています