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/ >>351 出来ました!! {}で囲むのは思いつかなかったです。 >>349 他プロセスとは同じプログラムを複数で同時実行したやつです それとファイルロックだとディレクトリにあるファイル1つ1つにロックしなきゃならないので ディレクトリにあるファイル全てにアクセス禁止するために アクセス禁止用ファイルを作りました スクリプトを動かすときは、「動きますように」と昭和する。 自分で考えているというのは大変良いことだと思うけど、聞きたいことがあるなら 環境くらいは書いてくれないと…… それに、使用中のファイルを rename することの何が問題なのかさっぱり解らない。 まず、何をするプログラムなのかを書いた方がいいと思うよ。 なんか書き込こもうとするとエラーが出て書き込めないわ ようするに てすと1シージーアイ OPEN(IN、”あああ.DAT”); すりーぷ(5); cLOSE(IN); てすと2シージーアイ リネーム(”あああ.DAT”、”AAA。DAT”); これを同時実行してもリネームはできなかったってこと 同時実行って言ったけど先にてすと1の方を起動して5秒以内にてすと2を起動です 他のプロセスが開いているファイルを、更新できるわけないだろ 2つのプロセスで、ファイル共有できるのは、read & read、の組み合わせだけ。 read & write, write & read, write & write は、共有できない >他のプロセスが開いているファイルを、更新できるわけないだろ 何を前提に話してんだ? 更新出来るから、ファイルロックなぞの方法が開発されたんじゃねーの? $ for i in 1 2 3 4 5 ; do > perl -le 'open my $f, q{>>}, q{foo.txt} ; print $f q{foo} ; sleep 2' & > done $ cat foo.txt foo foo foo foo foo >>361 更新 ”できないようにする" から ロックなんだよ。アホかw >>362 ん? (デフォの状態では)更新出来るから、 (更新出来ないようにするための)ファイルロックなぞの方法が開発されたんじゃねーの? ってレスだったんだが、、、 更新できるのは、同一プロセス内のマルチスレッドだろ だから、マルチスレッド・プログラミングは難しい ファイイルロックのモードは2より5のノンブロッキングの方が軽いですか? >>365 軽いかどうかで決めるんじゃない。 それが必要かどうかで考えろ。 ホント頭が悪いやつは、軽いかどうかの基準しか 持ち合わせてないんだよな。 上の2行は頭いいように見えたが 下の2行でホントに頭が悪い人だと思った。 誹謗癖はやめようね。嫌われるよ。というかすでに嫌われてると思うけど。 ノンブロッキングは、Node.js などが並行処理で、リクエストを受け付ける場合に使う。 こういうのは、プロ中のプロが使うもので、プログラムも順序通りには進まないから、 プログラミングが極めて難しい(イベントドリブン) 初心者は、ブロッキングを使え。 プログラムは一本道で、順序通りに進む >>358 少なくとも Linux では問題なく rename できるよ。 rename できないというのはシステムコールのマニュアルに書いてあるの? テストのやり方に問題は無かったの? こんなふうに同期させた方がいいと思うんだけど。 https://ideone.com/639PgP このようにflockをネストするのは問題ありますか? open(IN, "< $datafile"); flock(IN, 1); open(IN2, "< $datafile2"); flock(IN2, 1); close(IN2); close(IN); >>371 windows環境だけどopen中のファイルのrenameはできなかった 例えばtestディレクトリがあって、プロセスAでtestディレクトリにあるファイルのrenameやファイルの作成、 プロセスBでtestディレクトリを削除するとした場合 testディレクトリにファイルが残っているとrmdirが成功しないのでtestディレクトリを削除できない unlinkでtestディレクトリのファイルを全て削除してからtestディレクトリを削除しようとしても その間にプロセスAでファイルが作成された場合ディレクトリを削除できない だからディレクトリそのものをロックしたいっていうこと >>373 そういうことを先に書いてくれないと…… そうか、Windows ではできないのか…… プロセスAの処理が終わるまでプロセスBを待たせておきたいということなら 普通に mkdir でどうでしょう。可搬性も高い排他制御の定番です。 >>373 File::Path -> remove_tree http://search.cpan.org/ ~riche/File-Path-2.12/lib/File/Path.pm 何が目的でそのための何をしている状況なのかというのがいまだに理解できないんだけど、 そもそもそんな状況にしないやり方を考えた方がいいのかもしれない。 どうしても排他制御が必要なら例えばデータベースを使うというのは Windows でも出きると思う。 Windows のことは知らないからこれ以上はお役に立てそうに無い。 簡単に言うとディレクトリをmkdirで削除したいけど 削除しようとしている間にディレクトリ内にファイルを作られるとmkdirできなくて削除できないので ディレクトリ内にファイル作成もディレクトリ内のファイル読み込みも禁止にしたかったってこと 任意のプロセスがアクセスできるディレクトリを削除したいという要求自体が間違っている >>380 bbsディレクトリの中に各掲示板ごとのディレクトリがあって、さらにその中にログファイルや掲示板設定ファイルがある 削除したい掲示板は各掲示板のディレクトリごとに削除するしかないのでどうしても任意のプロセスがアクセスできる ディレクトリを削除するしかない test1掲示板の場合 ファイルはbbs/test1/logfile.datとbbs/test1/settei.datがあって 掲示板を削除する場合はまずこの2つのファイルを削除してtest1ディレクトリを削除するということです その掲示板とやらのディレクトリは本当に、自分のプロセスだけでなく任意のプロセスからもアクセスできるのか? であれば、ディレクトリのパーミッションが間違っている。自分のプロセス以外のアクセスを禁止せよ。 自分のプロセスしかアクセスできない前提であれば、好きなように自分で排他制御を行えばよい。例えば>>375 のように。 >>382 普通の掲示板やで 普通掲示板は誰でも観覧と書き込みができるので任意のプロセスからでも読み書きできる それとディレクトリの削除はブラウザからperlで書いたcgiを起動して削除するので パーミッションでのオーナーとかの判別はできないんや 掲示板のcgiが動いてるプロセスは掲示板を閲覧しているユーザとは関係なかろうが。 これ以上はperlの話ではなく、そのcgi固有の話だ。 ここでやる話ではない。 my(@aaa); @aaa = sort {$b <=> $a} @aaa; このとき$a,$bをmy($a,$b)やlocal($a,$b);と宣言するとエラーになります $a,$bはどのように宣言すればいいんですか? aとbはあらかじめ用意された特殊変数。 特殊変数は全部グローバル変数 >>378 他のプロセスに使われる前にディレクトリ名をランダムな名前に変更 するとよい。変更後に rmdir する。 1:投稿ファイルをロックして書き込み 2:投稿数ファイルをロックして書き込み 1の排他ロックが成功して2の排他ロックが失敗してタイムアウトになり書き込みできなかった場合 投稿数が実際の投稿より少なくなりが整合性がとれなくなる この場合下記のようにまとめてロックするのが普通? まとめ排他ロック 1の処理 2の処理 ロック解除 >>388 そういう場合はまとめた単位でロックを取ることが多い あるいはロールバックできるようにするしかないけど、それはたいてい難しい 1:投稿ファイルをロック 2:投稿数ファイルをロック 3:投稿ファイルを書き込み 4:投稿数ファイルを書き込み 5:投稿ファイルをアンロック 6:投稿数ファイルをアンロック PostgreSQLのTIMESTAMP形式の文字列を秒数(Perlのtime関数で取得したような状態)に直す関数教えて use DateTime::Format::Pg; print DateTime::Format::Pg->parse_datetime( '2016-08-21 23:50:01' )->epoch; 実行時間が0.15秒から0.2秒のperlスクリプトは重い部類ですか? >>390 データとは別にロック中か識別するためだけのロックファイルまたはディレクトリを用意するものなんじゃないの?>>389 のように 1:投稿数ファイルをロック 2:投稿数ファイルを書き込み 3:投稿数ファイルをアンロック 4:投稿ファイルをロック 5:投稿ファイルを書き込み 6:投稿ファイルをアンロック じゃだめなのかな。 それ投稿数と投稿が連動してないやん ロック 必要な書き込み全部 ロック解除 が普通 それは「普通」というより「手抜き」だね。最初はそれでいいと思うけど。 >>398 普通じゃなくて天才だよ。 完璧な答え。 まあ質問の直後にいきなり答えが書いてある それを分からないのが混ぜ返してるだけだ >>388-389 (書き込み時) 1:まとめロックようファイルを作る 2:まとめロック用ファイルを排他ロックする 3:投稿ファイルにを投稿を書き込む 4:投稿数ファイルに投稿数を書き込む 5:まとめロックの解除 (観覧時) 1:まとめロック用ファイルを共有ロックする 2:投稿ファイルを読み込んで表示する 3;投稿数ファイルを読み込んで表示する 4:まとめロックを解除 これが正しい >>393 何のために数字が振ってあるのか分かる? なんのため? プロセス間の整合を取るのにプロセス内の順序は全く意味ない数字と思うけど。 うーん、なんのためだろ?教えてくれないかな? > プロセス内の順序は全く意味ない数字と思うけど。 え? 順番を入れ替えても同じなると思ってるの? 例えば5 → 1 → 4 → 3 → 2 → 6 の順番で 実行しても同じ結果になると? ロックの話以前に、あんたが何が言いたいのかわからない んでなんのため? あと関係ない話しかしてないようだけど、同じになるって情報はどこから? そしてその話になんの意味があると思い込んでますか? >>390 が書いてあることは正しくて、 この順番通りの処理をすると不整合が起きない。 重要なのは書き込みを行う前に書き込むファイルすべてを ロックするということ。最初にまとめて行う。 こうすることでロックの間に処理が割り込まれず 正しく書き込むことができる。 ここまで正しい回答が何度も出てるのに、そのあとから間違った回答を自身満々にするのもすごいと思う ロックは常にプロセス間の整合のみ取るべし ごめん。外部仕様としてはこの場合正しかった。 内部的にはやってはいけないお手本のような無意味なロックがされてて、それで勘違いした。すまんかった。 確かにロックはプロセス間通信の一種で使う技術も同じか こうゆうのはスクリプトをプログラムと思ってる人と、プログラムの基礎的な部分から学んだ人とでは差が出そうだね windows7で文字化けファイル名を取得するとショートファイルで得られるようですが、 ロングファイルのビットの並びをそのまま得たいです。 指定して得るにはどうすれば良いでしょうか? ちなみにDOSなどでのコマンドは知っています。 `dir /b *.*` 次スレのテンプレに追加するから コマンドじゃなくてPerlでどうにかしたいのだけど my @file = split(/\n/,`dir /b *.* 2>NUL`); # あとは夏休みの宿題、な すまん、回答してるつもりだろうけど、頭悪い人に用はないんだ。 わざわざ何度も書いてる様だが、一番最初に(も)言った通りコマンド使うやりかたはできるから。 あと全レス会話の繋がりもなく、堂々と好き勝手なこと書く人間もしんどい。 いや、君の記述能力が頭悪いんだよ。 流行の言葉で言うとコミュ力やプレゼン力がない。 コマンド知ってますなんて言い方じゃ伝わらない。 少しは自分の不徳を省みたらどうか。 再現出来る環境無いんだけどWin32::GetLongPathNameはどうかな >>422 すまないがそれでは得られる文字は同じで、文字化け文字にはショートが適用されます。 おそらくwindowsに対するアプローチを変えないとだめだと思うのです。 >>421 いけたよありがとう。 API叩いてやりくりしてたけど、暫定的にそれを使わせてもらうよありがとう。 windowsは外部的にもさっさとunicode使ってほしいと思う。 >>420 その無駄な4行必要か?なんか書きたいなら頑張って回答書けば?(俺としては書かないで頂きたいけどな) まあとにかく特殊な環境なんだね。もう少し前提条件を書いたほうが早く欲しい回答を得られたと思うよ。 >>413 の書き方じゃ>>420 に文句を言う筋合いはないよ。 どうでもいいけど特殊な環境じゃなくてwindows標準の仕様かと なぜ化けるのか、と言う話だ CP932とunicodeが混在してる場合はどうすりゃいいですかって話じゃね ココ参考にして ttp://hirobanex.net/article/2015/03/1425807814 こういう呼び出ししても $teng->sql_builder->load_plugin('InsertOnDuplicate'); $teng->sql_builder->insert_on_duplicate(略) Can't locate object method "insert_on_duplicate" via package "Teng::QueryBuilder" で呼べないんだけどどうしたらいい? ちなみに __PACKAGE__->load_plugin('+SQL::Maker::Plugin::InsertOnDuplicate'); でもダメ PODに別パッケージから plugin生やす方法なんて書いてないでしょ マジレスするなら、 別の方法で呼べるか試してみる 何が起こっているのか調べてみる ってところか。 はっきりしてるのはhirobanexのとおりに書いてもエラーで動かない事 それも $teng->->execute なんていうタイポレベルの話じゃなく 根本的にどこか間違ってるけど、どこだかわからんということ $teng->sql_builder ってSQL::Makerを継承した状態でnewされてるんじゃないの? Teng::QueryBuilder = SQL::Maker だから これで動くんじゃないの? $teng->sql_builder->load_plugin('InsertOnDuplicate'); $teng->sql_builder->insert_on_duplicate(略) $teng->sql_builderでTeng::QueryBuilderのオブジェクトが帰ってくる これはほぼSQL::Makerを継承しただけなのでSQL::Maker::load_pluginを読むとどうやらクラスメソッドとして書かれている 実際SQL::MakerのPODにも継承したクラスでクラスメソッドとして呼び出す例が書かれている つまり $teng->sql_builder->load_plugin('foo') という書き方はオブジェクトから呼び出してるので間違い(おそらくTeng::QueryBuilder=HASH(0x000000)みたいなところに生えてる) Teng::QueryBuilder->load_plugin('foo') とするか ref($teng->sql_builder)->load_plugin('foo') とするか もしくはブログの例にもある通り独自のQueryBuilderクラスを用意するか >>429 この__PACKAGE__はどこに書いたんや?__PACKAGE__の意味わかってる? もう、馬鹿過ぎて哀れだ。実際にやりたいことは *SQL::Maker::insert_on_duplicate = \&SQL::Maker::Plugin::InsertOnDuplicate::insert_on_duplicate; ってことでしょ? もうこれでいいでしょ。POD すら読まないんじゃ助けようがないよ。 ごめん、言い過ぎた。とりあえず、正解が分らない段階で俺ならどうするかを書くよ。 まず、何をしているのかを POD で確認する。 POD では load_plugin についてはクラスメソッドとして使う例だけが書かれている。 ここで「おかしい」と思わなければならない。 オブジェクトメソッドとして使えないとは書かれていないのでソースコードを読む。 %INC を見ればソースコードの場所は分かる。 load_plugin は予想以上にシンプルだった。これで解決。 解決しなかった場合。 まず、SQL::Maker::Plugin::InsertOnDuplicate を明示的に use する。それで間違いなく呼べる。 SQL::Maker::Plugin::InsertOnDuplicate::insert_on_duplicate( $teng->sql_builder) あるいは $teng->sql_builder->SQL::Maker::Plugin::InsertOnDuplicate::insert_on_duplicate 好きな方でいい。これでうまくいくなら load_plugin で何かが間違っている。 デバッガを使うか、load_plugin を差し替えて動作を詳しく調べる。 Tengを使うのかどうか自分で選べるのなら、自分が理解していないものを使わないという選択肢がある。 他の人が選んでしかも使わなければならないという状況なら、選んだ人にどう使うのかを聞くといい。 多分ブログ書いた人やその人に教えた人はTeng本体と混ざって勘違いしたんだろうな Teng自体はインスタンスからもロードできるから この記事、オレオレメモだって自分で書いてるからわざわざつっこむのも野暮だけどOR検索の例もちょっとひどい。 どうしてこうなった? Windows の Strawberry Perl で、「Parallel::ForkManager」は使えますか? ---------------------------------------- use LWP::Simple; use Parallel::ForkManager; ... @links=( ["http://www.foo.bar/rulez.data" ;,"rulez_data.txt"], ["http://new.host/more_data.doc" ;,"more_data.doc"], ... ); ... # 最大30プロセスで並列的にダウンロードを行います my $pm = new Parallel::ForkManager(30); foreach my $linkarray (@links) { $pm->start and next; # forkさせます my ($link,$fn) = @$linkarray; warn "Cannot get $fn from $link" if getstore($link,$fn) != RC_OK; $pm->finish; # 子プロセスをexitします } $pm->wait_all_children; ---------------------------------------- の様なスクリプトで、数万ファイルをダウンロードしようとすると、 child process '-*****' disappeared. A call to `waitpid` outside of Parallel::ForkManager might have reaped it. のエラーを出しながら、メモリを全消費・開放を何度か繰り返した後に、 最終的には、「Out of memory!」で異常終了します。 Cygwin の Perl では、「Cannot get $fn from $link」エラーを出しまくりますが、 メモリを全消費する事はありません(異常終了もしません)。 windowsのForkは、表面上は同じように動作する仕様になっているが、 実際にプロセスやスレッド、CPUの動作が期待通りになってるかと言うとそれは違う。 ほとんどの場合が、unixとの互換性を保つための見せかけ。 if($hoge=~/(\d+)$hoge3$/){$hoge2=$1} これの意味は $hoge3が数字のみなら$hogeに代入し、$hoge2にも代入するという意味でしょうか? >>443 「WindowsのFork」の意味は分かりませんが(Windows用PerlのFork?)、 Cygwin の perl は、 C:\cygwin64\bin\bash --login -i -c "perl ... 等としなくても、Windows から直接起動出来るので、 あのスプリクトで直接起動しても、メモリエラーは出ませんでした。 Cygwin の perl を、Strawberry Perl の代わりに、、、と思ったら、 いきなり chomp が、CR+LF を削除してくれなかった。 >>444 perldoc.jp からのコピペです。 >>445 if ( 文字列 =~ /パターン/ ) もし「文字列」の中に「パターン」が含まれていれば、 if ( $hoge =~ /(\d+)$hoge3$/ ) { $hoge2 = $1 } もし「 $hoge 」の中に「 \d+$hoge3$ 」が含まれていれば、「 $hoge2 」に「 \d+ 」を代入 >>446 ありがとうございます。 他言語の底辺SEなので助かりました。 普段それを読む文化にない人がいきなり読めたら逆にすごいと思う PerlってPerlが分かる人だけの言語 Perl on Bash on Ubuntu on Windows10 での、 モジュールのインストールで、無駄に苦労した。 解決法: Config.pm の修正 Windows10 のコマンドプロンプトでも、 エスケープシーケンスが使えるらしい。 PROMPT $E[96m$T$E[3D $E[93m$P$G$E[37m$E[1C 懐かし C:\> prompt $e[1;36m[$d$s$t$h$h$h] $e[1;33m%USERNAME%@%COMPUTERNAME% $e[37m$p$_$g$s ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.1 2024/04/28 Walang Kapalit ★ | Donguri System Team 5ちゃんねる