Perlについての質問箱 63箱目
■ このスレッドは過去ログ倉庫に格納されています
CGIについての質問は板違いです。WEBプログラミング板でどうぞ。 CGIとPerlの区別がつかない人もWEBプログラミング板に行ってください。 (WEBプログラミング板: http://kohada.2ch.net/php/ ) このスレでは(CGI以外の)純粋にPerlのみに関係する質問を取り扱っていこうと思います。 スレ違いの質問にはスルーか、速やかな誘導をお願いします。 荒らしはスルー推奨。 "The duct tape of the Internet" こと、Perlについての質問箱です。 "There's more than one way to do it" ということで、 Perlの奥深さについて皆で語り合い、追求してまいりましょう。 www.perl.org/get.html Download Latest Stable Source (5.18.2) ▼前スレ Perlについての質問箱 61箱目 http://toro.2ch.net/test/read.cgi/tech/1381561905/ Perlについての質問箱 62箱目 http://toro.2ch.net/test/read.cgi/tech/1385039352/
それはそうと俺も稀にPerlやるんだが、 use utf8; use strict; use warnings; binmode STDIN, ':encoding(utf8)'; binmode STDOUT, ':encoding(utf8)'; binmode STDERR, ':encoding(utf8)'; これ毎回書くんだが、全部省略できないかの すぐこれ書くの忘れて文字コード関係でおかしくなるし、書いたら書いたで無駄に目障りなんだが・・・ # Hoge.pm package Hoge; use strict; use warnings; use utf8; binmode STDIN, ':encoding(utf8)'; binmode STDOUT, ':encoding(utf8)'; binmode STDERR, ':encoding(utf8)'; sub import{ strict->import; warnings->import; utf8->import; } 1; # script.pl use Hoge; # ただし@INCからHoge.pmが見つかるようにする そういやutf8なら binmode STDOUT, ':utf8'; で良かったか >>677 参照の -> を参照に対しては省略できるってだけだが。 それが凄いところ オブジェクト指向だって、ほんの小手先でちゃんと実用になるものを実装しちゃってる >>693 最低レベルな。 小手先で済ませちゃったから、それ以上の 便利な機能はライブラリ任せになっちゃって いつまでも標準が生まれなかった。 Perl6にさっさと移行すればいいのに 言語なんてそれでいいだろ 標準に拘っても何も得しない >>695 可読性の問題だ。 意味は全く一緒なのに、書き方を変えてどうする? 言語を変えるのと一緒だぞ どうせ定番の奴がデファクトスタンダードになるんだから同じことだ それは目的がニッチ過ぎたか利用者が少なすぎたからで、 どっちにしろ標準になんかならない Perl6 ? そういえばそうゆうものもあったな。ググると、 1年半前に正式安定版がリリースされたのか。知らなかった。 誰も、その事を話題にすらしていないし。 http://tamae.2ch.net/test/read.cgi/php/1162721943/ 「 Perl6/Parrotスレ - Part2 」 >>689 +690 PERL5OPTと組み合わせれば全て解消。 >>688 そうか?ディスクI/Oが絡まないようなメモリ上だけの操作ならさほど遅い感じしないけど。 まあ、単純なのと比べたら遅いけどね。 >>705 理論上完全に最適化できたとしても速度差は5倍以上あるよ $str = "みかん りんご ぶどう"; を・みかん ・りんご ・ぶどうというように文字の最初に・をつけるには どう置換すればいいんですか? join '', map { '・' . $_ } split ' ', $str; linux mint18 perl6のインストールについて $ sudo apt install rakudo パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 E: パッケージ rakudo が見つかりません どうしたらインストールできます? $ perl6 -v This is perl6 version 2015.11 built on MoarVM version 2015.11 すいません、解決しました メモリリーク検出になに使ってる? とりあえず昔からTest::LeakTrace使ってるんだけど いまはもっと便利なものがあったりするのかな? Perl/Qt は癖があるね、Perl/Qtとクラスを同時に使おうとするとなかなか大変。 テキストファイルを読み込むときに // (例えばfile://...) があると、そこから行末まで読み込めない現象が起きるんだけど どうしたらちゃんと読み込める? binmodeにしても解決しなかった >>717 open fp, "<$file"; while(<fp>){ print $_; } みたいな感じで読み込んでる ファイルハンドルからダブルスラッシュが含まれる行を読み込もうとするとダブルスラッシュが行末と誤認されるという解釈でいいんですかね 絶対になにかカンチガイしてるだろう。 単に出力のバッファリングで単に表示されてないだけとか。 もしくは自分で"//"以降を削除するような処理をしているとかだな。 正規表現の書き誤りがあやしい。 実際に、>>717 の方法で読ませればちゃんと読む筈 怪しい箇所を削っていって試せばいい カンチガイでした 別のところでCのコメント削除をしていて そこで消えてました テヘペロ C/C++のソースコードを読んで コメント削除したソースコード ifdefとかのプリプロセスしたソースコード typedef, struct, unionとかを抽出した結果 を得たいんだけどどうするのがいいだろう プリプロセスしたソースコードをcflowに渡すと 関数コールツリーを得られるから それらを使ってCのソースコード理解に役立てたい >>726 何が難しいのか、なんでそんなことをしたいのかよくわからん。 >>726 自前で作るって話からは外れるけど、Doxygenに突っ込むとかじゃダメなの? >>727 Cのソースコード理解のため 難しいのは例えばif x>=10 && (defined(y) || z==1)とか ifdef elif else endifとかの入れ子とか を正しくパースしたりすること structを抽出したあと それらの参照関係も図示したい >>727 簡単なら作ってgitとかにあげてほしい >>728 プリプロセスする前のコードだと重複したりすると思う gcc -Eとかだと #defineとかまで展開されるからそれは抑えたい gcc -E じゃだめなのか。 cpp のソースコードを読んでみるのがいいと思うよ。 昔、LSI-C 86 のプリプロセッサのソースコード読んで勉強したなあ。 >>726 cflowの中でプリプロセスするから事前にする必要はないと思うけど >>733 一部だけプリプロセスさせたいんです マクロとかはそのままの方がわかり易いので 例えば #define ERRLVL 5 #define WARLVL 3 とかなってるのをプリプロセスすると 数字に置き換わるので意味が判りにくくなる だけど#ifdefとかはプリプロセスしないと 例えば32ビット版の関数や構造体と 64ビット版の関数や構造体が重複してしまう CPAN に Text::CPP なんてのがあるよ。 そのままではご要望どおりじゃないと思うけど参考にはなるかも。 言いたいことはよく解る。 とりあえず、プリプロセッサの通常の動作から変更したいのは ・C ソースの中のマクロ置換はしない ・#define ディレクティブは用済みになっていないのでそのまま出力する といったところ? もし Text::CPP の作者がそれを有意義だと思ってくれたら、 なんとかしてくれる可能性もなくはないかもしれないな。 連絡先は README に書いてあるよ。 cpp をそのまま使うという方法もなくはないよ。 #define ディレクティブの前と C ソーステキストの前の行に #line ディレクティブを入れる。 cpp の処理結果には #line ディレクティブがあるから それを手がかりに元のファイルからコピーする。 この程度のことなら出来そうじゃない? あまり野暮なことはいいたくないけど、ファイルハンドルから行を読むんじゃなくて トークンを読んだ方がシンプルに書けるんじゃないかな。そうすれば while(( my $tokentype,my $str) = gettoken( $fh)){ if ( $tokentype == 'comment'){ case_comment;} elsif ( $tokentype == 'string'){ case_string;} みたいなやり方が出来る。気を悪くしないでほしい。本当にそう思ったんだ。 gettoken()を作ってread()で一文字ずつ読み込んでトークンを返すのは良さそうだけど トークンタイプはその時の状態が判らないと判別できないと思う //は普通の状態で現れたらコメント開始だけど "の中だと文字列 /*の中だとコメント文字列 tcpのIO::Socket使ってサーバーに対してconnectした後、closeせずに親プロセスは接続を維持したまま、 forkした子プロセスでサーバーから受信した大量の文字列をファイルに書くとかするには子プロセスが継承したソケットをどう破棄したらいいの? 現状では当然の事ながら親プロセスの受信待ちが完全に止まってしまって困ってます >>743 客先のサーバーの仕様とやらで複数の接続(connect)に対応していない模様(爆) >>744 親プロセスの接続を切れば複数接続じゃなくなると思う 解決しました fork()してから普通に子プロセス側で$socket->close();すれば良かったのですね。 ありがとうございました ヒント: print"Hello world!\n"; print "Hello world!\n"; print("Hello world!\n"); print ( "Hello world!\n" ); 1. print 文は実行が成功するとTrue(1)を返す 2. すべての引数を括弧で括るのでなければ、print というキーワードの 次に開き括弧を書いてはいけません ってだけの話。 print print print (1+2)+(4+5)+6+7; は、 print (1+2) を実行したあとに print 1+(4+5)+6+7実行して、 その戻り値1をプリントしてるだけ。 >>749 なるほど、すっきりしたありがとう。 >>748 これは逆に何のヒントか分からなかった。 >>741 そんな面倒なことを考えなくてもいいように gettoken を書くんだよ。 普通は C の文字列定数の中でわざわざ // を認識しない。どんなやりかたを考えてるの? 興味があるなら flex とかやったみたらどうかな。 >>751 文字列定数の中か外かはどうやって判別するの? ずいぶん前のことなのに反応があって嬉しいよ。 とりあえず、行継続もプリプロセッサディレクティブの処理もエラーチェックも無し、 コメントと文字列だけでいいなら flex ならこう書ける。 https://ideone.com/NbLVjc 本当は '"' みたいな文字定数も想定しなきゃまずいけどね。 もちろん、flex を使わなくてもできる。 yylex を手書きするなら、まず 1 バイト読んで switch ( c){ case '"': read_string(); break; case '/': read_comment(); break; みたいにするのが伝統的な方法だったりする。 この方法では switch から出る前にトークンを完結させる。 コメントや文字列定数の中と、それ以外の部分で文法が違うから 別の処理になっていると理解してほしい。 こうしなければならないわけではなく、テーブル駆動とかステートマシンが好みならそうすればいい。 重要なのは、yylex を 1 回呼べばトークンが 1 個完結しているということ。 もちろん Perl でも同じやり方はできる。できるけど…… Perl ですよ? 助けてくれるモジュールがあるんだから使ってみない? Parse::Lex とか。 flex をかじっておけば理解しやすいと思うよ。 >>753 それはcase文の文字で状態遷移してるのと等価 "があったら文字列の中の状態 /があったらコメント開始の1文字目の状態 モジュールを使ったのがネットにあったから使ってみたけど 期待と違ったから自作した >>753 あとread_commentの中で*が直後にくる場合はコメント内だけど 別の文字が来たらコメントじゃない read_commentとしてるけどコメントとは判別できない ネストしたブロックを正規表現でとりたくてperlreにある再帰パターンというのつかおうとしているですが(?>[^()]+)の部分うまくかきかえられません。 loop〜end loopの形にしたいのですが、 (?!)の使い方がわるいのかヒットしないorz (?>¥b(?!end loop|loop)で行けました。 ヒットしなかったのは再帰始まりのloopと干渉していたらしく、始まりをちゃんと書いたら動きました。 FW使わずにpsgi/slackを使おうとしてて、モジュールの名前と言うか場所に悩んでます(´・ω・`) pathがperl -I /hoge/lib/として、 /hoge/lib/Controller.pmみたいのを置きたいけど名前被りが嫌なので避けるための手法として /hoge/lib/myController.pmとか /hoge/lib/MyApp/Controller.pmとかあると思うんですが perlでこういう場合の命名規則?というかお約束みたいな名前ってあるんでしょうか。 /hoge/lib/作ってるサイトのドメイン/Controller.pm みたいにしようと思ったけど、 use 作ってるサイトのドメイン::Controller.pm こんなの使いまわし効かなさすぎて嫌すぎる お約束はない。 >こんなの使いまわし効かなさすぎて嫌すぎる ん? スクリプト内で動的に変更したいとか、そこらへん? じゃなきゃ普通に use XXXX::Controller で作っちゃうけど? あとは、物理的にパス切らない。くらいだよね? $ cat Hoge.pm package Hoge::Foo; sub hoge{ "hoge" } 1 ; $ perl -MHoge -le 'print Hoge::Foo::hoge' myController.pm 一個作って、中で切り分けちゃえば? どもです。 URLで言うexample.comみたいな不可侵領域?的なのが無いのかなぁと思った感じでした。 >>761 > もしプライベートな内部やプロジェクト固有の用途のために開発中のモジュールが 決して公開されることがないなら、 > 将来の公開モジュールと名前が 衝突しないことを確実にしてください。 > これは、予約済みの Local::* カテゴリを使うか、 Foo_Corp::* のように 名前にした戦を含めることで行えます。 これだあああ 戦ってのが謎ですが、Localディレクトリに入れることにします。 ありがとうございます! たぶん「した戦」→「下線」アンダーラインのことかと > Foo_Corp::* のように 名前に下線を含めることで なるほど… ちゃんと訳した上で漢字を変な読み方した状態でのタイポとはw 今とあるスクリプトを見たら 1 while(s/[\012\015]$//); こんなん書いてあったんだけど、 たぶん改行とおぼしきものは全部消すってことだと思うんだけど、 いらんもんまで消しすぎたりしてない? スカラー末の改行(の連続)を外す。 スカラー内の改行は外さない。 作者の意図通りに、余分なものは消さないと思うよ。 普通に、s/[¥012¥015]$//g ; すりゃいいと思うけど、、、 文字の末尾が012か015だったら消すんじゃない? 文字コードもわからないけど 動作は >>769 の通りだと思うけど 1 while が意味不明だな while 1 はマニュアルにも記載されてる基本的な手法 条件だけで実行が完了する 勉強し始めて1日で覚えるようなことを全然分からんようなやつが回答者ぶってるのかよ とりあえず一通り調べたけど、末尾に改行を使う文字コードはなかったから、 1 while(s/[\012\015]$//); これは本当に改行を削除したいならあらゆる方法の中で最善だと思われる 本当にかたっぱしから消したいのなら、だけど… と言うより $ が自動でその判定してるから、関係ないものは消えないはずなんだよね 取り敢えず、ベンチマーク。 $ cat bench.pl #!/usr/bin/perl use Benchmark qw( cmpthese timethese ) ; my $f = +( "42¥r¥n" x 1000 ) . +( "¥r¥n" x 10000 ) ; sub _gm { my $f2 = $f ; $f2 =~ s/[¥012¥015]$//gm ; } sub _while { my $f2 = $f ; 1 while $f2 =~ s/[¥012¥015]$// ; } cmpthese(timethese (undef, { while => '_while', gm => '_gm', })) ; $ perl bench.pl Benchmark: running gm, while for at least 3 CPU seconds... gm: 3 wallclock secs ( 3.36 usr + 0.01 sys = 3.37 CPU) @ 356.68/s (n=1202) while: 3 wallclock secs ( 3.06 usr + 0.00 sys = 3.06 CPU) @ 152.94/s (n=468) Rate while gm while 153/s -- -57% gm 357/s 133% -- あ、単純に変数最後の CRLF 削りたいだけなら、比べ物にならん程 chomp の方が早い。 local $/ = “¥r¥n” ; chomp $_ ; ActivePerlとCygwinの両方で動くようにしようと思うと、chomp使えないんだよな ん? どっちが悪いか知らんが、 local $/ = “¥012¥015” ; も効かんの? \rだの\nだの使ってることに神経を疑っちまうぜ と言うかutf8にさえ文字とみなされない文字を使ってる時点で… ところで以下の3つは全部挙動が違いので並列にベンチとっても無意味 chomp; s/[\012\015]$//gm; 1 while(s/[\012\015]$//); 特に真ん中のは色々とひどいことになると予想した >>780 I/Oと言うのはその名の通りIとOがあってだな >>781 ご指摘の通り俺が間違ってたわ。 chomp が違うのは同意 #!/usr/bin/perl use Benchmark qw( cmpthese timethese ) ; my $f = +( "42¥012¥015" x 1000 ) . +( “¥012¥015" x 10000 ) ; sub _gms { my $f2 = $f ; $f2 =~ s/[¥012¥015]$//gms ; } sub _while { my $f2 = $f ; 1 while $f2 =~ s/[¥012¥015]$// ; } cmpthese(timethese (undef, { while => '_while', gms => '_gms', })) ; Benchmark: running gms, while for at least 3 CPU seconds... gms: 4 wallclock secs ( 3.24 usr + 0.03 sys = 3.27 CPU) @ 391.13/s (n=1279) while: 3 wallclock secs ( 3.01 usr + 0.03 sys = 3.04 CPU) @ 155.26/s (n=472) Rate while gms while 155/s -- -60% gms 391/s 152% -- >>783 は上手く動いてねーw すまん。全面的の俺のレスは脳内から消してくれ。 連レスすまん。これを最後に消える。 s/[¥012¥015]¥Z//gm 出力を od -d -a で確認したから合ってると思う。 でベンチマーク取ったけど、記憶にある通りのベンチになった。 通りで>>777 、>>783 が遅いわけだわ。 うーん いくら考えても 1 while() と書いてる意味がわからん gオプションついてないから while の意味ないし 結果知りたいなら s/// の値を直で調べりゃ済む話だし 何故なんだ 誰か教えてください 量指定子の存在しない世界線なのか。 #!/usr/bin/perl -w use strict; sub hd { print '[', join(' ', map uc unpack('H2', $_), split //, $_[0]), "]\n" } my($lf, $cr, $n) = ("\012", "\015", "\n"); my $str = "$n$cr$lf$lf${cr}1${cr}2${lf}3$cr${lf}4${n}5$n$cr$lf$lf$cr$n"; $_ = $str; 1 while s/[\012\015]$//; hd($_); ($_ = $str) =~ s/[\012\015]$//g; hd($_); ($_ = $str) =~ s/[\012\015]+$//; hd($_); __END__ なお改行が \015 でも \012 でもそれらの組み合わせでもない環境があるので、 $ と \Z と \z の意味するところは元のコードが使われていた環境に依存する。 http://perldoc.jp/docs/perl/perlport.pod#Newlines ありがとう すごくよくわかった 1 whileの挙動をなにか勘違いしていたみたい そしてベンチマーク取ってみたら 1 while s/[\012\015]$//; よりも while(s/[\012\015]$//){} の方が微妙に速かった (すごく微妙なんだが 毎回1を評価しないでいい分の差??) そして s/[\012\015]+$//; は1桁近く遅かった そうだったんだ… ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.1 2024/04/28 Walang Kapalit ★ | Donguri System Team 5ちゃんねる