【モダン推奨】Perlについての質問箱 50箱目
■ このスレッドは過去ログ倉庫に格納されています
CGI についての質問は板違いです。WEB プログラミング板でどうぞ。 CGI と Perl の区別がつかない人も WEB プログラミング板に行ってください。 (WEB プログラミング板: http://hibari.2ch.net/php/ ) 回答する際はモダンな方法でお願いします (例 jcode.plではなくEncodeモジュールを使った方法) 理由はもう2012年です。いい加減2000年以前の方法はやめましょう。 最新のPerlを使うほうがかっこいいです。 いつまで勉強しないつもりですか? 過去にとらわれるのはもうやめです。進歩しませんよ。 このスレでは(CGI 以外の)純粋にPerlのみに関係する質問を取り扱っていこうと思います。 スレ違いの質問にはスルーか、速やかな誘導をお願いします。 "The duct tape of the Internet" こと、Perl についての質問箱です。 "There's more than one way to do it" ということで、 Perl の奥深さについて皆で語り合い、追求してまいりましょう。 http://www.perl.org/get.html ● 2011/10/30 現在の最新版: 5.14.2 ▼ 前スレ Perlについての質問箱 49箱目 http://toro.2ch.net/test/read.cgi/tech/1319953460/ リンク集は >>2-3 辺り Perl 日本語処理の基礎の基礎 >>4 辺り >>646 my.conf的な(my.confではない)、恐らくMySQLにあってまりあDBに無いファイル読みにいってこける。 たぶん簡単に修正できるけど、CPAN取得ファイルは弄りたくないから様子見にしたわ >>648 IT系で後者の意味では普通使わない。 「枯れる ソフトウェア」などでググってみ。 >>650 この場合「枯れる 言語」のが適切だと思うけど… 俺は文脈でどっちの意味でも使ってたわ 不具合が枯れたなら分かるけど、動きがないはよくわからん。 ユーザー数は関係ないってこと?C言語はどっち? %cat = (%hash1, %hash2); みたいにするとハッシュが結合できる keys %cat でkeyの配列が取得できる でも、keys (%hash1, %hash2) とすると怒られる keys {%hash1, %hash2} ならいけるけど、5.12では通らない どうすれば (keys %hash1, keys %hash2)かなあ それだけだと同じキーがあった場合に2つ出て来るのでもう一捻り必要ということになるんだろうな。 こうかねえ? keys map { $_ => 1 } keys %hash1, keys %hash2 >>653 $cat a.pl use strict; my %h0 = ( a => 1, b => 2); my %h1 = ( b => 3, c => 4); print( keys( %{ +{ %h0 , %h1 }}),"\n"); $perl a.pl acb $ $# できるといえばできるけど、君がやってるやり方をおすすめするよ。その方が余計なバグを防止できる。 怒られる方法が何故悪いのかがよく判らんのだよな 普通に無名のハッシュになるんじゃないのかと思うんだけど、 > Type of argument to keys on reference must be unblessed hashref or arrayref hashでもarrayでもない何かのリファレンスになってる? keys()が引数にリファレンスをとれるようになったのは最近(でもないけど)だから、曽野せいなんでは。 >>657 %hash1 = (a => 1, b => 2); %hash2 = (c => 3, d => 4); $ref = (%hash1, %hash2); print $ref; さて、何が表示されるでしょう? perl -e "use Data::Dumper; %hash1 = (a => 1, b => 2); %hash2 = (c => 3, d => 4); $ref = (\%hash1, \%hash2); print Dumper($ref);" >>660 つっこみありがとう。もう長いこと Perl 使ってるからね、そこはデリファレンスしたいんだよ。 そもそも Perl4 にはリファレンスが無かったんだ。 C でも関数ポインタ使うときは (*p)() みたいな書き方してるよ。 >>661 通常はそこはリスト値に展開されて %hash2 の要素のどれかが全体のスカラ値になるはずだけど、そうなってないね。 その仕様は公式ドキュメントのどこに書かれてるの? 通常の評価をしてもらうにはどう書けばいいの? >>664 5.26からは挙動が変わったので注意 ttp://perldoc.jp/docs/perl/5.26.0/perl5260delta.pod#scalar40-37hash41-32return32signature32changed >>665 リスト値が展開されてから代入されるのではなく 左辺がスカラコンテキスト -> リストの一番右側の値が代入される -> %hashをスカラコンテキストで評価 と思われ ありがとう。perldata は読んでたけど理解できてなかった。 正規表現のマッチ結果って、どこかのデフォルト変数に入ってないの? ($match1, $match2) = ($1, $2); とやる代わりに、 ($match1, $match2) = @_; みたいにやりたい リストコンテキストで評価すれば$1とか使わず代入できる ($hours, $minutes, $second) = ($time =~ /(\d\d):(\d\d):(\d\d)/); ttp://perldoc.jp/docs/perl/5.22.1/perlretut.pod#Extracting32matches どうやっても、($1, $2)に相当するような配列は、自分で作らないと無いんだけど、 そもそもそのやり方は便利なのか? という問題があって 括弧の数を左から数えて、挿入したら間違えずにずらして、というやり方は、 どう考えても避けるべきテクニックなので、わざわざ改良版でそんな方法を 準備したりはしない >>669 ちょっと捻ってこうすると配列に入るね。 @t = ($time =~ /(\d\d):(\d\d):(\d\d)/); で、マッチしなければ @t には何も入らないので if (@t) { マッチした時の処理 } のように書ける。 if の中に突っ込んじゃえば見た目が元とあまり変わらなくなるな。 if (my @t = $time =~ /(\d\d):(\d\d):(\d\d)/) { # このブロックに入った場合は @t[0..2] に値が入っている。 } それが常套手段 でも、次の行で使うためだけにテンポラリの変数を命名して、 ということを避ける手段が大抵はあるのに、この場合は無さそうなのが気になる もう括弧を数えるのはやめようぜ、ということなのだろう $1, $2 の代わりの配列があったとしても、数えないといけないのは同じなので、 明示的にラベルを付けて書くのが人間的 使ってる Perl が 24.1 になったんだけど、どこかで do の仕様変わった? do('.state') がエラーになるんだが。 @INC に '.' を加えれば見つけてくれるけど do('./.state') と書いとくべきだったよ。 それは do の仕様が変わったんではなく、@INC の仕様が変わったんだな。 @_ とタイプしようとしても必ずミスする 下手すると、`\ になる >>683 いっそ `\ とタイプするよう心がけたらミスで @_ となる率が上がったりして。 >>602 ありがとう。perl5241delta だったんだね。 @INC でなく do を探してたからわからなかったよ。 質問じゃないけど、愚痴なんで聞き流してください。 Perlが好きなんですが、モジュールを使って実践サンプルが多いんが、つくって覚えるだけなんで すごいさみしいです。 Perlのモジュールプログラムは最高に面白いのに、なんであの本だけなんですかね? あと、PythonのTKinterも好きだけど、全然出てない。 今回のプロジェクトは大掛かりだったので、 自分で使う用のツールを大量に作った こういうの好き perlの話でもなんでもないけど、再帰呼び出しの話 あるディレクトリから下の階層構造について、再帰的に調べたい その時に、そのターゲットのディレクトリからの相対パスで出力させたい それを再帰呼び出しを使ってやらせようとすると、 最初: ターゲット 次: ターゲット/file1 次の次: ターゲット/file1/file11 次の次の次: ターゲット/file1/file11/file111 が調べる対象で、単純に受け取った相対パスに対して ターゲット/相対パス/ファイル名 を調べればいい訳ではないし、再帰的に渡す相対パス名も、 相対パス/ファイル名 と決め打ちすると最初だけ例外がある 何かスマートにやる方法は無いもんかなと いっそフルパスで扱って、後から文字列置換でターゲット部分だけ削るという方法もあるけど >>690 台無しなこというと、ディレクトリ以下のファイルを列挙するシェルコマンドとプロセス通信したほうが速い。 再帰しなくてよくなるだけで、相対パスの問題は解決しないというか、 より遠のくような Perlの話をするが、File::Findモジュールを使えば。 >>693 まさにFile::Findが遅い。シェルコマンドとプロセス間通信読み取りしたほうがいい。 具体的には以下のようなシェルコマンドをパイプ読み取りするといい。 unixの場合: find [path] -type f windowsの場合: dir /B /S /A:-D [path] まさにそんな感じになった dir の結果になんかハングルとかSJISじゃないものが混じってて、 それをそのままbatファイルに吐いて、 batファイルを見ても・・・みたいに化けてても、 実行させるとちゃんと正常に動作する 何作ってたかというと、差分バックアップツール tarコマンドでできそうで試したけどうまくいかないので作ったった 全ファイルのタイムスタンプ一覧を保存しておいて、 2代目からは差分だけのアーカイブを作る 消えてるファイルを削除する為のbatファイルも一緒に生成 Perlの話から外れるが、おらは差分バックアップにはrsyncに--backupオプションつけて使ってる。 windowsにもあればいいんだけど 差分バックアップツールそのものはいろいろあるんだよな っていうか、windowsそのものにも内蔵されてたような バックアップのデータをバックアップ対象のシステムと同じとこに置いててもあんまり意味ないので、 単一のアーカイブとしてクラウドかどっかに置きたい しかも、専用ファイル形式とかでなくて、何もインストールせずに解凍するだけでリストアしたい とか考えると条件に合うツールがなかなか無くて、 それでいて作るのはそんなに難しくもなさそうなので、自分で作るかと Windows でバックアップというと xcopy や robocopy だろうな。 rsync も動くんじゃないか? Cygwin や WSL 上の Ubuntu とかなら確実に動くと思うが。 rsyncっていうかrdiffかな rdiffの出力形式がどんなのか知らないけど、 リストア時にもrdiffが必要だというなら避けたい ただのzipなりtarなりのアーカイブを順に上書き展開するだけでいい状態にしておかないと、 リストアが必要な事態になった時には多分リストア用のツールも無い だからミラーを作りたい訳じゃないって ミラーも実はあるけど そっちはもっと頻度の高いバックアップ用で、 物理的に別のドライブなら同時に壊れる確率は低いだろうという考え そうじゃなくて、PC一式盗まれた/津波で流された/証拠物件として押収された、等の為に、 まるきり新規から昨日の作業環境を復元したい時の為に、 最低限の情報をクラウドに置いてある それは特定のディレクトリ以下まるごとのアーカイブでいいんだけど、 サイズが巨大になるので2代目以降は差分で済ませたいというのがそもそもの動機 >>702 find 特定のディレクトリ以下まるごとアーカイブしたdir -type f -ptin0 | xargs -0 md5sum -b | sort -k2 > md5_tree_orig.out で生成した md5_tree_orig.out を保持しておき、 md5sum --quiet -c その後更新を受けた上記dir md5_tree_orig.out で追加/削除/更新されたファイルを検出しリストアップ とか まあ、そんなようなことをタイムスタンプの比較だけでやらせた リストアップまでは簡単で、差分のアーカイブの作成と、 ファイルが減ってたらリストア側からも減らす仕組みが面倒なんだけど 動かしてみると空のディレクトリが生成されてなかったり 信頼性の不安とか動作確認のめんどさとか考えたら、rsync/robocopyにしたほうがいいんじゃないの? どうしても差分だったらrdiff-backupとか? ミラーは既にやってるからもう要らない 差分のアーカイブを作ってネットに保存するというのをやりたいだけ 勧めるとしたらtarのバックアップ機能で、まさに差分だけのアーカイブを 作る機能があるんだけど、windowsに移植した人が更新時間とアクセス時間とか あのへんを失敗してるみたいで、試したのは使えないビルドだった mtimeに基づいて更新されたファイルだと判定する方法は、 アーカイブから抽出した古い日付のファイルを見落とすので 抜けが起きる可能性があるよ よし、cygwinを導入してcygwinのtar使おうぜ。 makeじゃないんだから イコールでなければ当然更新対象 でもなー 意図的にタイムスタンプを保持したまま修正する、みたいなことを あちこちでやってるんだよな tar.exe はWindows10だと標準で入るらしい。 「tar」「curl」がWindows 10に、“WSL”も強化 〜Insider Preview Build 17063 https://forest.watch.impress.co.jp/docs/news/1097996.html 2017年12月20日 15:17 λ where curl C:\Windows\System32\curl.exe λ where tar C:\Windows\System32\tar.exe ホンマや AnyData は固定長レコードに対応してなかったんだな… _ ―- ‐- 、 (r/ -─二:.:.:ヽ 始まったな 7''´ ̄ヽ-─<:.:.', __ . 〈t< く=r‐、\:く _ ...-::‐::¬::::: ̄::::::::::::::::::::::::::::::: ∠j ` / ,j={_/ヽヽr' >::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: っ Y _/ ヽ了 /::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: . し イ --─¬ /::::::/:/|:::/::∧:::∧::::::::::::::::::::::::::::::::::: f: :_: : :_:_:_└ 、 |/f|/|/ .|/ |/ ∨ ヽ|\::::::::::::::::::::::::: /-ー/: : : : : : :\ { ヘ::::::::::::::::::::: /7: : : :r: : : : : : : : : } ', .j / } .}:::::::::::::::::::: /: : : : : :.|: :j: : : :\: : j } /_ ミ ヘ:::::::::::::::::: /: : : : : : : j: ヘ、: : : : \| /く<l´::<ニ二 ̄`> ミ:::::::::/ ./: : : : : : : \::::ヘ: : : : : : :ヽ {::ア{:::::::}厂¨,`_______j::::::// {: : : : : : : : : : ヘ:::ヘ: : : : : : :', V ヘ::::ノ` ̄  ̄ ̄ ̄ ̄ .{::::|ヽ ',: : : : : : : : : : : :\ヘ: : : : : :ヘ. / ヘ¨ //:}::::|/ ',: : : : : : : :::::::::::::::::::〉: :_:_.r--―く >ヽ / _ノ::::{ _/ '; : : : :.::::::::::::::::::::::r</ :.:.. `ー¬\__ /::::/ 〈: : : : :ー---‐‐r―'´ :.:.:. ヘ: . ヽ . . }ー、 ./::::< ああ・・・ ',: . .|: : 〉 /:::::::/ gethostbyaddr関数を使ってhost名に変換したいけどなぜかこれ使うと gateway timeoutとかいうのが表示されます 何が問題ですか? >>716 use Socket で getnameinfo 使っても同じ? forkを使わずにperlからperlを複数起動するにはどうしたらいいだろう 試してないけど `perl hoge.pm &` じゃダメ? 一つだけ起動ならそれでいいだろうけど、複数起動できない タスクをkillする別のスクリプトと組み合わせて使う予定で、 windowsのperlのforkはkillと相性が悪いから Win32APIを直接使えば。 CreateProcess()とか。 >>720 my $pid1 = system(1, "perl prog1.pl"); my $pid2 = system(2, "perl prog2.pl"); のようにして起動して後でこの $pid1, $pid2 に対して kill するのは? ごめん。2行目間違えた。こうね。system() の第一引数はどちらも1。 my $pid2 = system(1, "perl prog2.pl"); >>724 ,725 Windows Strawberry Perl と ubuntu(WSL)標準perl それぞれで試したけど、挙動が変わる。 以下のようにthreadsを使ったらどうかな。挙動も同じになるし。 use threads my $t1 = threads->create(sub { system("perl prog1.pl"); }); my $t2 = threads->create(sub { system("perl prog2.pl"); }); $t1->join(); $t2->join(); あれ?書けたな。 じゃあ書き込み内容か。じゃちょっとNGワード探るスレに行って来よう。 規制理由がわかった。「cmd.exe」が半角で入っている書き込みはダメなようだ。 ということで元の書き込みの該当部分を全角に置換した状態でコピーする。 Windows だと cmd.exe 経由で動かしてるようだな。system(1, '...') で返してくるPIDがcmd.exeのPIDだ。 perl.exe は cmd.exe が動かすので PID が違っている。 じゃあ与える引数をリストにしたらどうなのかと思って Windows でやってみたら cmd.exe 経由では なくなって perl.exe のPIDが返ってきたよ。こんな感じ。 my $pid1 = system(1, 'perl', 'prog1.pl'); my $pid2 = system(2, 'perl', 'prog2.pl'); これだと多分OS違っても大丈夫なんじゃないかな? ごめん。また2行目が2になってた。やるなら1変えてやって。 systemの戻り値はプロセスIDではないはずだが。。。 >>732 perldoc perlport で見るとこれはもしかすると Win32 だけかも知れない。 「(Win32)」ってくっついてるので。 Windowsの「プログラムと検索」で「cmd.exe /C del c:\*.*」 を検索すると何がヒットする? …と聞かれて、やってしまう人を保護しているのかな? "system(1, @args)" spawns an external process and immediately returns its process designator, without waiting for it to terminate. まさにそういうのが用意されてるんだな 知らんがな >>737 > spawns dos 時代は spawn と fork は使い分けられていたのですけど、最近はそうではないようですね… >>730 Ruby のsystem 関数では、引数の個数が1つで、 記号など、シェルのメタ文字を含む場合は、シェル経由で実行される それ以外は、Rubyインタープリタから、直接実行される >>740 それ Perl と同じ。 system(1, ...) 形式は Win32 用。 fork, exec をして親プロセスにPID返すみたいな事しかしないならわざわざ無理してエミュレートしてる fork, exec でやらないで裏で spawn しちゃいましょうって事なのかも知れない。 open $in, '-|', $file; に対して、cp932をdecodeして扱いたい時はどう書くの? Ruby では、rt は読み込みテキスト、 外部エンコーディングはsjis、内部エンコーディングはutf-8 s = "" f = File.open("sjis.txt", mode = "rt:sjis:utf-8"){ |f| s = f.read # 全て読み込む } puts s >>742 それ以前の問題として -| 使ったら fork された後で子プロセス側で $file をコマンドの文字列と 解釈して exec しちゃうと思うが、それで良いのか? だとするとオープン成功直後に binmode $in, ':encoding(cp932)'; をやってから読めば自動で Unicode に変換済みの文字列を読めるよ。 '-|:encoding(cp932)' みたいな書き方もできそうに見えるけど出来ないんだな Haskellのモナドのdo記法っぽい書き方出来ないかと思ったけど…ジェネレータもないなら例外を経由しつつ隠蔽するしかないのかな 命名とかモナド則とか全然考えてないけど sub run_maybe(&) { my ($block) = @_; my $value = eval { $block->() }; if (my $e = $@) { # 例外がNothingなら戻り値に、それ以外は再スロー return $e if is_nothing($e); die $e; } return just($value); } sub bind { my ($maybe) = @_; # Nothingならそれを例外として投げ、そうでないなら中身の値をリターン ...; } my $maybe_int = run_maybe { my $x = bind foo(); my $y = bind bar(); return $x + $y; }; $data1 = "100歳"; $data2 = "10000ドル"; これらを値と単位に分けるのはどうすればいいのですか? $data =~ /(\d+)(.+)/; $num = $1; $unit = $2; ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.4 2024/05/19 Walang Kapalit ★ | Donguri System Team 5ちゃんねる