トップページ⇒php
1001コメント349KB

Perlコーディング初心者質問スレ Part 44

■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん2005/10/17(月) 00:47:17ID:???
Perlのコーディングで困ってる人のスレです。

【投稿する際の注意】
質問するときは内容をよく吟味してから投稿してください。
「コマンドの意味がわかんない」とかはマニュアル見ましょう。
回答者さんは何でも屋じゃありません。

1: 自分はこういう事がしたい。
2: それでこんな風にやってみたが・・・
3: こんなエラーが出て上手く行かなかった。

最低でも1と3が無いと誰も答えられないよ。
ソース貼る時は、全角スペースでインデント忘れずに。
良い回答は良い質問から。一緒に勉強しましょう。

過去ログやお勧めサイトは >>2-10
0797nobodyさん2005/11/29(火) 20:56:33ID:???
エラーログみてぐぐったりしてたら半分解決しました。みなさんどうもありがとうございました。とりあえずapacheスレへ移動しようと思います。
http://72.14.203.104/search?q=cache:NDE5CiEokLAJ:pc5.2ch.net/test/read.cgi/mysv/1087514426/101-200+apache2+%E6%8C%87%E5%AE%9A%E3%81%95%E3%82%8C%E3%81%9F%E3%83%91%E3%82%B9%E3%81%8C%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93&hl=ja
http://72.14.203.104/search?q=cache:-QDvNjZ_4LoJ:sakaguch.com/PastBBS/0034/B0017459.html+apache2+%E6%8C%87%E5%AE%9A%E3%81%95%E3%82%8C%E3%81%9F%E3%83%91%E3%82%B9%E3%81%8C%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93&hl=ja

こちらのとおり#!perlだけにしたら動きました。でもレンタル鯖にうpするときにいちいち書き換えるの面倒なので引き続き試行錯誤っす。
0798nobodyさん2005/11/29(火) 21:19:22ID:jT6RPKnv
かわいそうになってきたので助言。

ホームページの管理ディレクトリ → d:\www\my_web\
Perl のインストール先 → d:\usr\

こうすれば #!/usr/bin/per って書ける。
借りてるサーバーが /usr/local/bin/per であれば、ローカルでの Perl の
インストール先は /usr/local ってなる。
0799nobodyさん2005/11/29(火) 21:23:39ID:???
お前の頭がperだよ
0800nobodyさん2005/11/29(火) 21:24:42ID:jT6RPKnv
l が抜けてた orz
0801nobodyさん2005/11/29(火) 22:17:45ID:???
         -─=三=- 、
       /イイイ   ヽ三\ヽ\
      ///イ   ___    ヽ トトト
      i:|:/ミ  -_-__--_−_-_ トト|:i
      |:|:|イ   へ、 ̄ /ヽ   |:|:|
      |:|:||   _、   ,.-_、 |:|:|
      ト:!:|  ヽ´´´ノ ヽ´´´ノ |:|リ
      ヽ_|    ̄ ノ  丶 ̄  |_ノ
         | \/ (_i  i_)\/ |
        |  | /  ̄  \ | | <売り上げ120億、利益20億ある。どんな弁護士使ってでも潰す!
         \ -=^^=- /
           ヽ   ̄  ノ
0802nobodyさん2005/11/30(水) 00:15:31ID:???
>>801
「潰す」じゃなくて「叩く」だ、ボケ。
0803nobodyさん2005/11/30(水) 00:17:24ID:???
>>802
「叩く」じゃなくて「追求させていただきます」だ、ボケ。
0804nobodyさん2005/11/30(水) 12:15:39ID:BadrrQNs
>>801-803
ここはPerlスレだ、ボケ。
0805nobodyさん2005/11/30(水) 12:36:29ID:???
>>804
さげろ、ボケ。
0806nobodyさん2005/11/30(水) 13:27:40ID:???
ぜったいageてなんかあげないんだからねっ!!
0807nobodyさん2005/11/30(水) 14:38:09ID:???
下げたお
0808nobodyさん2005/11/30(水) 14:47:51ID:???
(;^ω^)・・・
0809nobodyさん2005/11/30(水) 15:33:38ID:???
ネタでもいいけど、せめて何かperlishなネタを書けよ…
0810nobodyさん2005/11/30(水) 16:05:54ID:???
$ichi $ni

このふたつの変数を足し算した結果を出力したいのですが、どうすればよいのでしょうか
0811nobodyさん2005/11/30(水) 16:37:17ID:???
真ボスキタ━━━━━(゚∀゚)━━━━━!!
0812nobodyさん2005/11/30(水) 17:27:28ID:BWMdiBVJ
print $san;
0813nobodyさん2005/11/30(水) 18:47:17ID:???
print $ichini;
0814nobodyさん2005/11/30(水) 20:25:37ID:???
やべwwwwクソワロタwwwwwww
0815nobodyさん2005/12/01(木) 00:24:08ID:0lJ9PdU1
$pring
0816nobodyさん2005/12/01(木) 01:33:14ID:???
そろそろ面白くないからもういいよ。
0817nobodyさん2005/12/01(木) 03:20:18ID:???
$twelve
0818!omikuji2005/12/01(木) 04:22:29ID:???
!omikuji
0819nobodyさん2005/12/01(木) 07:44:14ID:???
>>816
$omaegana
0820nobodyさん2005/12/01(木) 07:45:09ID:???
>>816
$kukiyome
0821nobodyさん2005/12/01(木) 07:45:42ID:???
>>816
$chin kasu
0822nobodyさん2005/12/01(木) 08:22:49ID:???
空気読めてないのはお前らだろ。
0823!omikuji2005/12/01(木) 08:23:34ID:???
!omikuji
0824nobodyさん2005/12/01(木) 08:55:16ID:???
>>822
$kukiyome chin kasu
0825nobodyさん2005/12/01(木) 08:55:48ID:???
816=822

↑$pugya-
0826nobodyさん2005/12/01(木) 08:56:22ID:???
>>822
$pan katte koi
0827!omikuji2005/12/01(木) 09:09:32ID:???
!omikuji
0828nobodyさん2005/12/01(木) 09:12:14ID:???
複数の戻り値を得たい時に

my ( $hoge1, $hoge2, $hoge3 ) = hogehoge();

とする事はできるのですが

my ( $hoge1, %hoge2, @hoge3 ) = hogehoge();

な感じで違う種類の戻り値を得たい場合は
どのように書けば良いのでしょうか?
0829nobodyさん2005/12/01(木) 09:31:46ID:???
>>828
http://www.kt.rim.or.jp/~kbk/perl-5.8/perlfaq7.html#how_can_i_pass_return_a__function__filehandle__array__hash__method__regex_
http://www.kt.rim.or.jp/%7Ekbk/perl5.005/perlsub.html#Pass_by_Reference
http://www.kt.rim.or.jp/%7Ekbk/perl5.005/perlref.html
08308282005/12/01(木) 10:11:00ID:???
>>829を見ました。
つまり、1発で取り出すのは無理で、
リファレンスの配列を作り

my @tmp = hogehoge();
my $hoge1 = $tmp[0];
my %hoge2 = %{$tmp[1]};
my @hoge3 = @{$tmp[2]};

上記のような感じで
取り出せって事で良いですか?
0831nobodyさん2005/12/01(木) 10:34:52ID:???
グローバル変数を使うといいお( ^ω^)
0832nobodyさん2005/12/01(木) 11:18:37ID:???
>>830
それでもいいし、

sub hogehoge {
  my($scalar, $array, $hash) = @_;
  ${$scalar} = 'hoge';
  @{$array} = (0..5);
  %{$hash} = (foo => 1, bar => 2);
}
hogehoge(\$hoge1, \@hoge2, \%hoge3);

でもいいよ。
0833nobodyさん2005/12/01(木) 11:40:24ID:6Wvm5Rjx


グラフ表示に、GD使ってかいてんですけど、
モニタで見るには、気にならないのですが、
プリントアウトすると、結構荒くてもひとつなんですが。
他に、綺麗にperlでグラフ表示させるのってなんかあります?
0834nobodyさん2005/12/01(木) 11:52:22ID:???
>>833
綺麗かどうかは知らんけど、GDを使わないものも色々あるよ。
http://search.cpan.org/search?m=all&q=Graph&s=1&n=100
0835nobodyさん2005/12/01(木) 12:27:34ID:kcqRAlrr
FTPサーバにHTMLファイルをアップロードするCGIというのは実現可能でしょうか?
0836nobodyさん2005/12/01(木) 12:30:35ID:???
>>833
GDの使い込みが足りない。
設定次第で驚愕するほど美麗なグラフも出力できるぞ。
0837nobodyさん2005/12/01(木) 12:33:39ID:???
>>835
CGI経由でやらなきゃいけない事か考え直した方がいいと思うけど。
http://search.cpan.org/~gbarr/libnet-1.19/Net/FTP.pm
0838nobodyさん2005/12/01(木) 12:39:03ID:???
>>837
ありがとうございます。
どうしてもCGI経由でやりたいので助かります。
08395662005/12/01(木) 16:30:41ID:???
以前メタ文字関連で質問させて頂いた者です。

$word = quotemeta("a b c");
print $word;

このようにすると、出力文字列が
a\ b\ c
となってしまいます。
quotemetaは/[A-Za-z_0-9]/にマッチしない全ての文字の前にバックスラッシュをつけるようですが、
$wordに\または.がある場合のみ、この2文字の前にバックスラッシュを入れるということは可能でしょうか。

掲示板のログ検索機能なのですが、
検索対象文字に\を入れるとエラーが出て、
.を入れると全記事がヒットしてしまう状況に悩んでいます。
>>566も併せて参照していただけると有り難いです。
0840nobodyさん2005/12/01(木) 16:50:23ID:???
掲示板で検索って言ったらマルチバイト文字も来るだろうから、
入力された文字に対してquotemetaを使ったら\が入りまくって意味不明なことになるからNG
08415662005/12/01(木) 17:39:55ID:???
\Q\Eについて調べました。
>>566のソースから
- if ($data[6] =~ /^(?:$ascii|$twoBytes|$threeBytes)*?(?:$words[$_])/) {
+ if ($data[6] =~ /^(?:$ascii|$twoBytes|$threeBytes)*?(?:\Q$words[$_]\E)/) {
こうする事で解決できました。
0842nobodyさん2005/12/01(木) 21:07:49ID:???
かなり説明わかりにくいのですが、わかるかたヘルプです。
.pl から .pl に飛ばしたいと思っています。
 Location: test.pl
とやって read( STDIN, $hoge, $ENV{'CONTENT_LENGTH'} );
で、$hoge に情報がくっ付いてくる(&nama=boku)のようにしたいのですが
どのようにすれば出来るのでしょうか?
0843nobodyさん2005/12/01(木) 21:53:39ID:???
if ($AAA =~ /$BBB/) {・・・

$AAAが$BBBという文字列を含んでいるなら・・・
としたいのですがこのままだとエラーがでてしまいます。
どのように修正すればいいのでしょうか?
08448432005/12/01(木) 21:57:30ID:???
Perlコーディング・・・もしかしてスレ違い?失礼しました
0845nobodyさん2005/12/01(木) 21:57:44ID:???
if ($AAA =~ /\$BBB/) { foo(); }
0846nobodyさん2005/12/01(木) 21:58:15ID:???
>>842
Locationで飛ばしてPOST送信にしたいということになるのかな。
それは不可能。POSTで送らないとならない理由があるの?
単に情報を付けたいだけならQUERY_STRINGを使うべし

>>843
if ($AAA =~ /\Q$BBB\E/) {
08478432005/12/01(木) 22:03:36ID:???
>>845-846
ありがとうございます。
>>846さんの方法で解決できました。
0848nobodyさん2005/12/01(木) 23:34:13ID:6Wvm5Rjx
>>834
うーむ、いろいろとありますな・・・。
今は、時間がないので、チェックできませぬ。

>>836
GD::Graph使ってるんで、
ttp://www.linkclub.or.jp/~ma3ki/webutil/gdgraph/howtograph.html
これぐらいは、できるんだけど、円グラフなんか、印刷すると枠や、ラインがガタガタで、
設定とかあります?
とりあえず、最新バージョンに上げてみましたが、なにもかわらずでした。orz
0849nobodyさん2005/12/02(金) 00:01:04ID:???
>>846さん
ありがとうございます。見た目的に長いURLになっちゃうのが格好悪いな…
って思っちゃったぐらいです。
このたびは大人しく諦めることにします。
0850nobodyさん2005/12/02(金) 00:04:42ID:???
>>849
一時ファイル作るとか、Cookie使うとか
0851nobodyさん2005/12/02(金) 02:01:48ID:lZKmMfsr
入力値にa〜z、A〜Z、0〜9、-、_、しか入力されないように
チェックしたいと考えています。

if($abc =~ /[^a-zA-Z0-9]/){ }
大小英字、数字に関しては上記の様にする事で実現できたのですが
-と_の記号を含めてチェックするには上記にどのように含めて
記述したら良いのでしょうか?
0852nobodyさん2005/12/02(金) 02:14:27ID:???
>>851
http://www.kt.rim.or.jp/~kbk/perl-5.8/perlretut.html#using_character_classes
08538492005/12/02(金) 02:43:53ID:???
>一時ファイル作る
なるほど! Cookieは理解不足にしてもこれならいけそうです Thx!!
0854nobodyさん2005/12/02(金) 07:56:04ID:???
>>853
セッション
0855Perl初心者2005/12/02(金) 09:40:50ID:???
>>851
あれ、これでダメなの?
\がいるのかな?

/[^a-zA-Z0-9_-]/
0856nobodyさん2005/12/02(金) 12:41:38ID:zgDZ/Pi8
>>855
/[^a-zA-Z0-9_\-]/
エスケープしてくだちぃ
0857nobodyさん2005/12/02(金) 12:52:02ID:???
[]内の最後に書く分には必要ないっしょ<エスケープ
0858nobodyさん2005/12/02(金) 12:56:28ID:???
みんな\dとか使わないの?解りやすいから0-9とか使ってンノ?
0859nobodyさん2005/12/02(金) 13:20:04ID:???
文字クラス内だと\d使えない(はず)
0860nobodyさん2005/12/02(金) 13:28:19ID:???
>>859
使えるよ

% perl -e '"ab123cd" =~ /([\d]+)/ and print "match: $1\n";'
match: 123
0861nobodyさん2005/12/02(金) 14:22:38ID:???
教える側の知識がグダグダなスレ。
0862nobodyさん2005/12/02(金) 14:39:45ID:???
> 852 名前:nobodyさん(sage) 投稿日:2005/12/02(金) 02:14:27 ID:???
> >>851
> http://www.kt.rim.or.jp/~kbk/perl-5.8/perlretut.html#using_character_classes

> '-'がキャラクタクラスの中の最初か最後のキャラクタであった場合、
> 通常のキャラクタとして扱われます。[-ab]、[ab-]、[a\-b]はすべて等価です。

> \d\s\w\D\S\Wの省略記法はキャラクタクラスの内側でも外側でも使うことができます。
> 以下はその例です:
>
> /\d\d:\d\d:\d\d/; # hh:mm:ss 形式の時間表記にマッチ
> /[\d\s]/; # 数字または空白にマッチ
0863nobodyさん2005/12/02(金) 14:48:03ID:???
>>861
WebProg板なのでご了承下さい
0864nobodyさん2005/12/02(金) 15:38:16ID:???
すごいことになってるな。

# 例えば、aだけにマッチなら
/^a+$/ または !/[^a]/
0865nobodyさん2005/12/02(金) 16:09:40ID:???
どっかのベンチでは\wを使うほうが速かった
0866nobodyさん2005/12/02(金) 16:49:33ID:???
use Benchmark;
my $count = 2000000;
my %codes = ();
my $wt = 'omaemona-itteyosijisakjen_07211919童貞';
$codes{'code1'} = q{
1 if /[^a-zA-Z0-9_-]/;
};
$codes{'code2'} = q{
1 if /[^a-zA-Z0-9_\-]/;
};
$codes{'code3'} = q{
1 if /[^\da-zA-Z-]/;
};
$codes{'code4'} = q{
1 if /[^\w-]/;
};
timethese($count,\%codes);

結果:激しくバラバラ
0867JAPU ◆lVJAPUTeX. 2005/12/02(金) 18:21:04ID:???
ごきげんよう。

\w はロカールを考慮する (場合がある) という話があったなぁ。sage
0868nobodyさん2005/12/02(金) 18:46:19ID:McNady6M
置換の正規表現内で、if文を二つ以上使うにはどうすればいいですか?

$hoge =~s/hoge/
条件1 ? 式 a : 式 b ;
条件2 ? 式 c : 式 c ; /e

うまく実行されないみたいなんですが。。
0869JAPU ◆lVJAPUTeX. 2005/12/02(金) 18:58:26ID:b5HKaxNa
はにゃーん

こういうことをやりたいのかな?
$hoge = "creamy fancy magical";
$hoge =~ s{(\w+)}{
if($1 eq "creamy") { "mami" }
elsif($1 eq "magical") { "emi" }
else { "unknown" }
}ge;
0870nobodyさん2005/12/02(金) 19:20:52ID:McNady6M
よくみたら一つの三項演算子が機能してないだけでした。

$iの先頭に'う'が含まれてたら
$hoge1、ふくまれてなかったら$hoge2を、
$tmpに代入して、$hogeを書換したいんです。
でも、$iがなんであろうと、$hoge1のほうが代入されてしまうんです。
どうすればいいんでしょうか。

$uaaaa = ~s/うあああああああ/
$i = ~m!^う! ?
$tmp=$hoge1 : $tmp =$hoge2;
$tmp
/e;
0871nobodyさん2005/12/02(金) 19:23:07ID:???
$hogeを書き替えたい→$uaaaaを書き替えたい、の間違いです。
すみません。
0872JAPU ◆lVJAPUTeX. 2005/12/02(金) 19:34:04ID:???
何をやりたいのか解読できないのだけど。

とりあえず気づいた点を指摘。
$foo =~ s/regex/replacement/;
$foo = ~s/regex/replacement/;
この2つは異なる (空白の位置に注意) けどそれは大丈夫かな?
後者は
$foo = (~s/regex/replacement/);
と介錯されるので,99.99%くらいの確率で意図しているものとは違うと思う。

参考演算子は
$var = ($foo eq "bar")? $baz: $zot;
みたいな形に書いたほうがわかりやすいとおもう。


- 実際に実行したコード (それ単体で完結したもの)
- やりたいこと
- 意図した結果/実際の結果
を書けば暇な人が答えるかも。
0873nobodyさん2005/12/02(金) 22:05:38ID:???
>>872
久々に見た
本物?
0874nobodyさん2005/12/02(金) 22:12:22ID:???
おれも久々に見た。_gunzipは見ないけど・・
0875JAPU ◆lVJAPUTeX. 2005/12/02(金) 23:07:32ID:???
コードのインデントは乱さないように,変数は命名規則に従うように,きっちりと書くのがここでのたしなみ。もちろん,use strict; しないなどといった,はしたないプログラマなど存在していようはずもない。

【変数の役割】
素直にそのまま解釈すると,
$uaaaa ... 書き換えの対象
$i ... この先頭に "う" が含まれているかどうか (*) で処理を分ける
$hoge1 .., (*) が真 (成り立った) の場合置換する文字列
$hoge2 ... (*) が偽 (成り立たない) の場合に置換する文字列
でいいのかな?

【コード】
$uaaaa = "ふえいとうあああああああもえもえ";
$i = "うる星やつら";
$hoge1 = "せいばー";
$hoge2 = "とおさかりん";

$uaaaa =~ s{うあああああああ}{ ($i =~ /^う/)? $hoge1: $hoge2; }e;
print "$uaaaa\n";

>>873
本物です。:)
http://www.japu.org/ (近況更新しておきました。)
0876nobodyさん2005/12/02(金) 23:55:46ID:???
>>875
http://www.japu.org/about_japu.html の掲示板が潰れているよ。
0877nobodyさん2005/12/03(土) 00:22:10ID:???
何この痛いコテ
0878nobodyさん2005/12/03(土) 01:09:43ID:???
真性だから触るな
0879nobodyさん2005/12/03(土) 01:10:08ID:IjoTBsN+
「うぐぅ」っておまえはまだ粘着してんのかよ
0880nobodyさん2005/12/03(土) 08:04:29ID:9ILkhYC5
ありがとうございます。
三項演算子というのがよくわかってないのかも。
/で始まるパスの前には'http://yahoo.co.jp'をくっつけるようにして、
それ以外で始まるパス(../とか)の前には'http://yahoo.co.jp/mail/tegami/letter/'というURLをくっつけるようにしたいんです。
以下の方法だと、パスがなんであろうと後者のほうがくっついてしまうようなんですが、三項演算子の部分、どこが間違ってるんでしょうか。
(これを置換の式に組みこみたかったんです)

#!/usr/bin/perl
print "Content-type: text/html\n\n";

#パス名を /hoge.jpg に設定
$path='/hoge.jpg';

$host="http://yahoo.co.jp";
$directory="http://yahoo.co.jp/mail/tegami/letter/";

#問題の三項演算子
$path=~m/^\// ? $tmp=$host : $tmp=$directory;

# URLにして表示
print $tmp.$path;
exit;

結果
http://yahoo.co.jp/mail/tegami/letter//hoge.jpg
0881nobodyさん2005/12/03(土) 08:08:54ID:9ILkhYC5
ありがとうございます。
三項演算子というのがよくわかってないのかも。
/で始まるパスの前には'http://yahoo.co.jp'をくっつけるようにして、
それ以外で始まるパス(../とか)の前には'http://yahoo.co.jp/mail/tegami/letter/'というURLをくっつけるようにしたいんです。
以下の方法だと、パスがなんであろうと後者のほうがくっついてしまうようなんですが、三項演算子の部分、どこが間違ってるんでしょうか。
(これを置換の式に組みこみたかったんです)

#!/usr/bin/perl
print "Content-type: text/html\n\n";

#パス名を /hoge.jpg に設定
$path='/hoge.jpg';

$host="http://yahoo.co.jp";
$directory="http://yahoo.co.jp/mail/tegami/letter/";

#問題の三項演算子
$path=~m/^\// ? $tmp=$host : $tmp=$directory;

# URLにして表示
print $tmp.$path;
exit;

結果
http://yahoo.co.jp/mail/tegami/letter//hoge.jpg
08828802005/12/03(土) 08:14:38ID:???
おお、すみません。
>>872をよく見て、
$tmp=($path=~m/^\//) ? $host : $directory
と書き直したらちゃんと動作しました。
ただの見た目の問題かと思っていたら、
こういうふうに書かなければ動かないんですね。
ありがとうございました。
0883JAPU ◆lVJAPUTeX. 2005/12/03(土) 09:11:41ID:???
($path =~ m/^\//)? ($tmp = $host): ($tmp = $directory);
または
$tmp = ($path =~ m/^\//)? $host: $directory;

三項演算子として使うなら後者が一般的。前者の書き方をしたければ if/else を使うほうが良いと思う。


>>881 のコードが動かないのは,
$path =~ m/^\//? $tmp = $host: $tmp = $directory;
は演算子の優先順位の関係で
($path =~ m/^\//? $tmp = $host: $tmp) = $directory;
と解釈されてしまうので,条件によらず最終的に $directory が代入されてしまうため。

ちょっと説明不足でしたね。
0884nobodyさん2005/12/03(土) 10:49:25ID:H4lHBq9R
質問させてください。

$str = q{<span id="hoge">あいうえお</span>あいうえお</span>}

最初のあいうえおだけマッチする正規表現はどう書けばいいのでしょうか?
$str =~ /???/;
0885nobodyさん2005/12/03(土) 11:15:01ID:???
>>884が考えて失敗した正規表現の .* を .*? にしてみな
0886nobodyさん2005/12/03(土) 11:17:02ID:H4lHBq9R
出来ましたありがとうございます
0887nobodyさん2005/12/03(土) 23:13:08ID:???
>>884
Perl関係ないけど言っておこう。

<span>...</span>タグはインライン要素なので、ホントは入れ子にできない。
lattice(で合ってたっけ?)にもできない。
× <span>foo<span>bar</span>hoge</span>

入れ子にできるのはブロック要素。
0888nobodyさん2005/12/03(土) 23:30:02ID:???
>>887
こらこら、適当なことを言うな。span要素は入れ子にできる。
ttp://www.w3.org/TR/html401/struct/global.html#edef-SPAN

というか所謂インライン要素はXMLで言うところのmixed contentなんだから、
文字データと共に自由に混交できる (他にスキーマで制約されていなければ)。
0889nobodyさん2005/12/03(土) 23:37:38ID:9N6MOM3Z
連想配列のソートについて質問です。
配列には
@NEW[0]='a,3,C';
@NEW[1]='c,1,B';
@NEW[2]='b,2,A';
のように納まってます。
@NEW[0]='c,1,B';
@NEW[1]='b,2,A';
@NEW[2]='a,3,C';
結果はこのように数字部分をソートする方法を考えてます。

foreach my $data ( @NEW ) {
($youso1,$youso2,$youso3) = split (/\,/,$data);
$xx[$data] = $youso2;
}
%yy = sort values (%xx);
@NEW = keys %xx;
このようなものを考えたのですがうまく動きません・・・
お知恵をください・・・
08908892005/12/03(土) 23:38:52ID:???
× %yy = sort values (%xx);
○ %xx = 〜 です

ageてすみません ○| ̄|_
0891nobodyさん2005/12/04(日) 00:09:50ID:???
>>889
まず @NEW[0]='a,3,C'; は $NEW[0]='a,3,C'; だ。
次に $xx[$data] = $youso2; は配列の添え字部に $data が入ってる。恐らくやりたいのは $xx{$data} だろう。
で、 %yy = sort values (%xx); は値を基準にソートしたつもりだろうが、
valuesを使った時点でキーを含まないリストになってしまうので
このようにする @NEW = sort { $xx{$a} <=> $xx{$b} } keys %xx;
この(889の)方法はハッシュのキーを使うため重複が纏められてしまう。
ついでにハッシュはキーの順番を保持しないので最後に @NEW = keys %xx; こうすると意味が無い。

まあ多少効率は落ちるかも知れないが @NEW = sort { (split',',$a)[1] <=> (split',',$b)[1] } @NEW; の1行でできるんだけどな。
0892nobodyさん2005/12/04(日) 00:11:41ID:???
基本の Schwartzian Transform なら
my @new = ('a,3,C', 'c,1,B', 'b,2,A');
@new = map{ $_->[0] } sort{ $a->[2] <=> $b->[2] } map{ [$_, split(/,/)] } @new;

ハッシュ使うなら
my @new = ('a,3,C', 'c,1,B', 'b,2,A');
my %hash = map{ (split(/,/))[1] => $_ } @new;
my @new = @hash{sort{ $a <=> $b } keys %hash};
0893JAPU ◆lVJAPUTeX. 2005/12/04(日) 00:13:24ID:???
>>889

まずは,ハッシュ (Perl4まで連想配列と呼ばれていたものは,Perl5でハッシュと呼ばれるようになりました) のキーを指定する方法に誤りがあります。
× $xx[$data] = $youso2;
○ $xx{$data} = $youso2;
前者は (通常の) 配列 @xx の要素にアクセスする際の記法です。

ここで %xx のキーに元データが入っていますので,keys %xx を並べかえればよいということになります。
比較するためのデータはハッシュに値として入っているので,下記の通り記述すれば動くことでしょう。
@ordered = sort { $xx{$a} <=> $xx{$b} } keys %xx;

※ ハッシュ,sort などについては,マニュアルを参照してください。
- http://perldoc.perl.org/
- プログラミングPerl (オライリー)
- Programming (O'Reilly)

----
手段は違いますが,このような処理をする際の定石を示しておきます。
my @ary = ("a,3,C", "c,1,B", "b,2,A");
# @tmp0 = (["a,3,C", 3], ["c,1,B", 1], ["b,2,A", 2]);
my @tmp0 = map { [$_, (split /,/)[1]] } @ary;
# @tmp1 = (["c,1,B", 1], ["b,2,A", 2], ["a,3,C", 3]);
my @tmp1 = sort { $a->[1] <=> $b->[1] } @tmp0;
# @ordered = ("c,1,B", "b,2,A", "a,3,C");
my @ordered = map { $_->[0] } @tmp1;
print "@ordered\n";
----
これを一文にまとまるとこうなります。Schwartzian Transform と呼ばれています。
my @ordered = (map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [$_, (split /,/)[1]] } @ary);
# 詳細は Effective Perl を読むと良いです。
08948892005/12/04(日) 00:34:13ID:???
>>891-893
なるほど・・・よくわかりました。ハッシュには順番がないのですね。
Schwartzian Transformで簡単にできたので、これとハッシュについて学んでみます。
ありがとうございました。
0895nobodyさん2005/12/04(日) 09:41:27ID:???
Fedora Core 4 + Perl 5.8.6 です。質問お願いします。

Perl ローケルの一時的な変更の方法を教えてください。
strftime( '%d/%b/%Y', localtime() );
で 01/Oct/2005 みたいな結果を期待したのですが、 01/12月/2005 のような日本語に合わせた結果になって困っています。
それとも素直に月名を配列に入れるのが得策でしょうか?

調べたところ i18n ファイルを変更すべしと書いてあるサイトに多数出会ったのですが、
他のアプリケーションには一切影響を与えたくないため何か別の方法があればお願いします。
0896nobodyさん2005/12/04(日) 10:39:23ID:???
>>895
strftime を使わなければいいんじゃね?

sprintf '%02d/%s/%04d', (split /\s+/, localtime)[2,1,4];
■ このスレッドは過去ログ倉庫に格納されています