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/ >>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桁近く遅かった そうだったんだ… オレ速度はあまり気にしないから、いつも素直に s/(?:¥r?¥n)+$//; の感じだな。 ¥b入れた方がいいのかもしれないけれど入れたことはない。 $とって、gつければ、改行全部きえるはずだよ。 (行単位に分離されてそうだけど。。。) >>789 一体どんな計り方をしたんだ。 http://perldoc.jp/docs/perl/perlperf.pod http://perldoc.jp/docs/perl/perlcompile.pod#The32Decompiling32Back32End #!/usr/bin/perl -w use strict; use Benchmark qw(cmpthese); my($lf, $cr, $n) = ("\012", "\015", "\n"); for my $str ("$n$cr$lf$lf${cr}1${cr}2${lf}3$cr${lf}4${n}5$n$cr$lf$lf$cr$n", "abc$n", 'abc') { cmpthese(-5, { ws => sub { $_ = $str; 1 while s/[\012\015]$//; 1 }, wb => sub { $_ = $str; while (s/[\012\015]$//) {} 1 }, qu => sub { $_ = $str; s/[\012\015]+$//; 1 }, }); print "\n"; } __END__ これぐらいシンプルな正規表現なら エンジン内でのバックトラック >> 文自体の反復 >= ループ構造 文字列内に [\012\015] にマッチする文字があればあるほど qu の方が速くなる。 こんな計り方↓ #!/usr/bin/perl use strict; use warnings; use Benchmark qw/:all/; 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" x 100; cmpthese -5, { '1while' => sub {$_ = $str; 1 while s/[\012\015]$//;}, '1while_g' => sub {$_ = $str; 1 while s/[\012\015]$//g;}, quantifier => sub {$_ = $str; s/[\012\015]+$//;}, while_g => sub {$_ = $str; while (s/[\012\015]$//g){};}, while => sub {$_ = $str; while (s/[\012\015]$//){};}, }; __END__ 同じwhileでもgオプションつけると微妙に速くなる 面白い >>792 自分の感覚と真逆の結果なんで -Mre=debug して調べたら、 [\012\015]$ だと 固定長だからエンジンが動作を最適化して最初から末尾しかみないんだな。 だから文字列自体が長くなると逆転が起こると。勉強になったよ。 #!/usr/bin/perl -w use strict; use Benchmark qw(cmpthese); my $n = "\015\012"; my $sa = $n x 500; # 全文字にマッチ my $sf = ($n x 250) . ('a' x 500); # + の場合前半に長くマッチした上で失敗する my $sl = ('a' x 500) . ($n x 250); # 後半に長くマッチ my $sn = 'a' x 1000; # マッチしない my $su = ('a' x 998) . $n; # 末尾のみ cmpthese(-5, { wa => sub { $_ = $sa; 1 while s/[\012\015]$//; 1 }, wf => sub { $_ = $sf; 1 while s/[\012\015]$//; 1 }, wl => sub { $_ = $sl; 1 while s/[\012\015]$//; 1 }, wn => sub { $_ = $sn; 1 while s/[\012\015]$//; 1 }, wu => sub { $_ = $su; 1 while s/[\012\015]$//; 1 }, qa => sub { $_ = $sa; s/[\012\015]+$//; 1 }, qf => sub { $_ = $sf; s/[\012\015]+$//; 1 }, ql => sub { $_ = $sl; s/[\012\015]+$//; 1 }, qn => sub { $_ = $sn; s/[\012\015]+$//; 1 }, qu => sub { $_ = $su; s/[\012\015]+$//; 1 }, }); __END__ こちらこそ勉強になりました まぬけな質問 >>787 やとんちきなベンチマーク >>792 でも 役に立つ(?)こともあるんですな Perlに向いてるIDE教えて デバッグ機能とかはいらない 補完と文法チェックとオートインデントが欲しい CPANとの連携機能はどっちでもいい みんなメモ帳レベルのテキストエディタで書いてるの? どこまでがエディタでどこまでがIDEなのか分からないが、それなりの機能は欲しい 自作関数とかも補完して欲しいしなあ サンクス vscode調べてみる pythonもVBもバージョン上がると別物になる そして大抵古い方が使いやすい pythonはそろそろLinuxのデフォルトが3になりそうだけど Perlはそんな気配全く無いよねw システム付属のスクリプト言語っていう立ち位置がかつてのPerlからPythonに変わったからなあ >>810 Unicode Character 'ATOM SYMBOL' (U+269B) おいらのPCでは、コピペしてもフォントが対応していないので出てが。 環境によってはどうやってもアトミックにならんのでは 日本だとparameterもargumentもどっちも引数と訳して区別しないから、 何故ARGなのかピンときにくいな 引数は単に引数ってだけ。その使われ方は決まっていない。 例えば言語によっては関数の引数で戻り値を返すことだってできる。 つまり引数=パラメータではない また関数の引数の多くはパラメータになるが、 引数だけがパラメータではない。 環境変数でパラメータを渡すことも有る つまり「この関数の引数はすべてパラメータであり、引数以外のパラメータは取らない」 のような使い方をする なぜ $_ が ARGなのかというと 正式名称が「デフォルトの引数」だからである。 ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.0 2024/04/24 Walang Kapalit ★ | Donguri System Team 5ちゃんねる