トップページ⇒php
988コメント342KB

CGIに依存しないPerlの話題一般

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2001/05/31(木) 21:49ID:bKRSBFew
・コマンドラインからのPerl活用
・モジュール、オブジェクト指向プログラミング
・Perl6や.NET対応など
・各種GUIツールキット(Perl/Tk, Gtk-Perlなど)
・他言語による拡張(Inline::*, XS, Swigなど)

についてマターリと語り合うスレッドです。

#CGI関連の話題は、なるべく専用スレッドで。
0131_gunzip2001/07/17(火) 06:47ID:???
>>129
ふぅ。オプティマイザの副作用の気がするなあ。

Perlが与えられたスクリプトを実行する際、コンパイルと実行段階の間に
オプティマイズという段階があって、定数値の埋め込み、
余計なシンボルテーブル検索の削除等を行うことになっている。

例えば、
print 4 + 5;
は、始めのOPコードへのコンパイルの段階で
「4(const)と5(const)をスタックにプッシュ、次にスタックから二つ値を取り出し、
それらを加算(add)、その値をprintで標準出力に出力せよ」
というコードが生成されるのわけだけれど、
Perlのオプティマイザは4と5が数値定数であるから、これらを予め計算して
「9をprintで標準出力に出力せよ」
というコードに修正する。(Perlのオプティマイザの働きについては
他にも色々とあるので、詳しく知りたければop.cのpeep()でも眺めてくれ)
0132_gunzip2001/07/17(火) 06:48ID:???
------------
で、今回の場合、問題の
out << "==========終了済み==========";
についてだけれど、(ちょいと端折った)
out はBEGINブロックのpadlist内に閉じこめられた$stdoutを常に返す
*プロトタイプが空の*サブルーチンなので、オプティマイザによって
その返す値 $stdout に置き換えられる。
(サブルーチン呼び出しに伴う負荷を押さえるために、プロトタイプが空であり、
かつ定数値を返すものはその値に置き換えられることになっている。
constantプラグマなどがその良い例。)
(但しこれは正確ではない。&をつけて呼び出されたものは置き換えられない事に注意。)

で、次
「$stdout (blessed "main")」<< "==========終了済み==========";
シフト演算子"<<"(Perl内部の"left-shift"コード)の子は
何れも定数であるため、オプティマイザは(上でも見たように)
これを予め実行した結果に置き換えようとし、その結果、オーバーライドされた
メソッド(3-7行目)が呼び出され、「"==========終了済み=========="」が出力される、
というわけ。

これらは全て**実行段階前**に行われるので、exit()やdie()の順序は意味を持たない。

試しに、
*out = sub(){ $stdout };
の()を外したり、後ろのout呼び出しに&プレフィックスをつけると、
表示されなくなることを確かめてみればいい。

#いつもながら、間違っている箇所があれば訂正してくれると嬉しい。
0133名無しさん@お腹いっぱい。2001/07/17(火) 07:07ID:???
_gunzipたん萌え
0134名無しさん@お腹いっぱい。2001/07/17(火) 07:34ID:???
>>_gunzip
あなたマジすげえ。
01351292001/07/17(火) 14:56ID:???
なるほど!
コンパイル時に実行される計算だったわけですか。
確かに-cスイッチの元で実行しても"終了済み"と印字されました。

しかし、"*out = sub(){...}"を"sub out(){...}"に変更すると
そのような置き換えは発生しないのですが、これは何故なんでしょうか。
お手数かけますが、教えてください。


>>133-134
激しく同意っす。
0136_gunzip2001/07/17(火) 17:43ID:???
>>135
>しかし、"*out = sub(){...}"を"sub out(){...}"に変更すると
ちょっと確認するけれど、これは
-----------------------------------
#!/usr/bin/perl
BEGIN{
    use overload '<<' => sub{
        my($self, $str) = @_;
        print {$self} $str;
        return $self;
    };
    my $stdout = bless \*STDOUT;
}
sub out(){ $stdout };
exit;
out << "==========終了済み==========" << "\n";
------------------------------------
のようにoutの宣言をBEGINブロックから外に出した場合だよね?
0137_gunzip2001/07/17(火) 18:02ID:???
-----------------------------------
#!/usr/bin/perl
BEGIN{
    use overload '<<' => sub{
        my($self, $str) = @_;
        print {$self} $str;
        return $self;
    };
    my $stdout = bless \*STDOUT;
    sub out(){ $stdout };
}
exit;
out << "==========終了済み==========" << "\n";
------------------------------------
ならOKだが....。
サブルーチンがインライン化されて定数値に置き換えられるためには
そのサブルーチンのプロトタイプが空であり、かつ、その返す値が
単なる定数値(4とか"hello"とか)であるか、又は、
**レキシカルスコープを持ち、かつ他から一切参照されない**
(この場合の$stdoutがそう)スカラー値でなくてはならない。
01381292001/07/17(火) 18:16ID:???
あれ?
ぬぬ、>>137のつもりでしたが確かに>>137ならOKでした。
勘違いだったらしいです。スミマセソ。
0139名無しさん@お腹いっぱい。2001/07/18(水) 07:51ID:???
お、今search.cpan.orgをみるとTie::Staticなるモジュールが。
基本的な考え方は>>64と変わらないものの、
IDに安全な値を使っているのでTie::Staticの方がマトモか…。
しかし見ていて飽きないですね、CPAN。
0140_gunzip2001/07/18(水) 23:41ID:???
日本人でCPAN登録者って居るのかな....?
(Jcode.pm以外見たことがない)
0141名無しさん@お腹いっぱい。2001/07/18(水) 23:49ID:???
perl に付いては凄いがメール欄は凄くない(・∀・)
0142名無しさん@お腹いっぱい。2001/07/18(水) 23:58ID:???
>>140
CGIメーリングリストの人に何人かいなかった?
0143名無しさん@お腹いっぱい。2001/07/19(木) 00:00ID:???
SpreadSheet::ParseExcelも日本人
0144名無しさん@お腹いっぱい。2001/07/19(木) 00:01ID:???
>>140
DBI MLのかわいさん (例のエクセルのやつとか、バーコードのやつ)とか
perl-ooのみやがわさん(macバイナリカッターとか)とか
20人ぐらいはいると思う。

# どうでもいいけど、梅田紀伊国屋コンピュータ書コーナー配置換え。
#もともとおかしかったけど、さらに逝って良しな書店になった。
#場所は便利なのになあ。
0145名無しさん@お腹いっぱい。2001/07/19(木) 00:05ID:???
日本人いますよ。
といってもこのJcode.pm含めて3人しか知りませんが。
…しかも全部文字コード関係だし(^^;
http://search.cpan.org/search?dist=CGI-ConvertParam
http://search.cpan.org/search?dist=ShiftJIS-Regexp
http://search.cpan.org/search?dist=Jcode
ガンバレ日本人!

ところでcpan2とsearch.cpanって何処が違うんでしょ。
付加分散の為?
0146JAPU2001/07/19(木) 00:30ID:???
こんなのもあるぞ。
http://search.cpan.org/search?dist=Roman
0147_gunzip2001/07/19(木) 05:57ID:???
>>142 いや、 CGIメーリングリストには入っていないので....。
>>143 あ、ど忘れしてました。川合氏ですね。(バーコードも)
>>144
macバイナリカッターの方は初耳だった....。
梅田紀伊国屋といえば、何時行っても人が多い
&& コンピュータ書コーナーは隅っこで本も少な目という印象があるな...。
京橋紀伊国屋が出来てからは、大抵そこで済ますようになったし、
無ければ新地のジュンク堂に行けばいいということもあって、梅田の方には最近殆ど行かない。

>>145
いろいろ教えてくれてありがとう。
search.cpan2.orgもあるみたい.。(中身は何もないけれど)
http://search.cpan2.org/
やはり負荷削減のためか.....。
http://take23.org/news/2001/01/26/cpan2.xml

>>146 ありがとうございます。探せば色々と有るものですね。

# 自分も何か貢献出来るようなネタがあるかな...と思ったが....
# CPANを探せば大抵は揃っているようですね。
0148____________________2001/07/19(木) 06:30ID:???
Cの構造体みたいな書き方で
$s = new A();
$s->foo = "hoge";
$s->bar *= 50;
(foo, barはメンバ)
みたいな書き方は出来ますか?
トリッキーなのでもイイです。
0149_gunzip2001/07/19(木) 06:47ID:???
>>148
lvalue属性を使えば簡単に実現出来るよ。
詳しくはperldoc perlsubの"lvalue subroutine"セクションや、
attributeプラグマのマニュアルを読んでくれ。

#!/usr/bin/perl -w

package Point;

use strict;
use overload q{""} => sub { sprintf("(%d,%d)", $_[0]->x, $_[0]->y) };

sub new
{
    my $class = shift;
    return bless { x => $_[0], y => $_[1] }, $class;
}

sub x :lvalue method
{
    shift->{ x };
}

sub y :lvalue method
{
    shift->{ y };
}

package main;

our $p = new Point(1, 15);
print "\$p = $p\n";

#X座標を5倍、Y座標に20代入
$p->x *= 5;
$p->y = 20;
print "\$p = $p\n";
0150名無しさん2001/07/19(木) 07:42ID:???
http://hp.vector.co.jp/authors/VA017578/software.html
ここのShellExtCtrlってソフト
結構使いやすい
Windowsで.plファイルが.batみたいに使えるようになる
0151名無しさん@お腹いっぱい。2001/07/19(木) 10:32ID:mCZ55RKw
>> 150

ActivePerl付属の pl2bat じゃだめなの?
ドロップすれば @ARGVにファイル名が入るのは一緒だし。
0152名無しさん@お腹いっぱい。2001/07/19(木) 19:00ID:???
pl2batよりはSOSを奨励したい。
パイプ繋がるから。
01531482001/07/19(木) 23:16ID:???
>>149
Thanks!
0154わ、2001/07/20(金) 03:51ID:O.8zSDuM
sa
0155名無しさん@お腹いっぱい。2001/07/20(金) 06:56ID:C8dQMlbs
こんな質問、いいのかな・・・。

最近perlを憶えたのですが、自分で色々課題を出して解こうとしています。
しかし記念すべき第一号の課題から躓いてしまっています・・・。

あるディレクトリ内にファイル名に全く統一性のないファイルが複数あるとします。
そのファイルのどれだか分からない一部のファイル群に『HOGEHOGE』という文字
があり、それを『FUGAFUGA』という文字に変更するにはどうすれば良いのでしょう
?HOGEHOGEという文字は一つのファイルに一度しか出てきません。

スクリプトを作ろうとしたのですがうまく行かず、結局ここの方に頼ることに・・・。
また、この作業をperlを使ってコマンドラインから実行する方法も是非。
0156名無しさん@お腹いっぱい。2001/07/20(金) 07:39ID:???
>>155
どちらかと言うとPerl初心者コーナーの方が適当だと思いますが。

とりあえずヒントだけ。
rename($oldfile => $newfile); # 名前変更
use IO::Dir;
@files = IO::Dir->new($dir)->read; # ディレクトリ$dirにあるファイル名全てを得る
0157名無しさん@お腹いっぱい。2001/07/20(金) 12:26ID:???
perl -e"for(<*HOGEHOGE*>) {$old=$_;s/HOGEHOGE/FUGAFUGA/;rename($old,$_);}"

カレントディレクトリ(サブディレクトリは除外)限定の場合
01581552001/07/20(金) 18:30ID:69JZH5Is
>>156
>>157
すみません。訊き方方が悪かったです。
HOGEHOGEはファイル名ではなく、ファイルの中に書いてある内容です。
0159名無しさん@お腹いっぱい。2001/07/20(金) 20:27ID:???
>>155
まずうまく逝かなかったスクリプトを上げるべきだと思うのだが、
いかがかな?

それが無いようであれば、「教えて君」と見なし、以後放置するよ。
01601552001/07/20(金) 23:36ID:8VNGZ9tA
ごめんなさい。
【Perl 】初心者コーナーPart5に移動しました。
0161名無しさん@お腹いっぱい。2001/07/23(月) 23:33ID:D.yGMh3Q
誰かASのVisualPerlのβ版使ってる?感想キボンヌ。
0162_gunzip2001/07/25(水) 20:21ID:???
http://aspn.activestate.com/ASPN/Downloads/PerlNET/
Perl.NETはbeta3になっているけれど、試した人いるかな?
(今のところWindows2000,NTでしか動作しないそうなので試せない。)

Perl.NETで、MS Windows上でもPerlで単体実行ファイル(PEじゃないが)や、
DLLを作り、それを C#, C++,JScriptから呼び出したり、逆にC#, C++のクラスライブラリを
Perlから簡単に利用できるようになるらしいな。(実際は知らんが)
0163名無しさん@お腹いっぱい。 2001/08/05(日) 06:15ID:???
use strict;;;foreach(ord(
pack(chr(++$*+$*+++$**$*.
$*),$=))+--$* .. ord(pack
(chr($*+$*+++$**$*.$*),$=
))+--$*+$*++-(($*-$***$*)
)+$*+++$***$*-$*---$**$*,
$***$***$**$*){push@_,$_}
;foreach($***$**$*+$*/$*,
$***$**$**$*+$**$*,$***$*
*$**$*+$*,$***$**$**$*+$*
*$*-$*/$*,$**$**$**$**$*-
$**$**$*+$*,$*-$*,$**$***
$**$*-$*-$*/$*,$**$***$**
$*-$*,$***$***$*+$**$*-$*
/$*,$**$**$*-$*/$*,$**$*,
$***$***$*+$*/$*,$**$**$*
*$**$*-$**$**$*+$*,$***$*
**$*-$*/$*,$**$*,$***$***
$*+$*/$*,$***$**$*+$*+$*/
$*,$***$**$**$**$*-$**$**
$*+$*,$***$**$*-$*/$*,$*-
$*,$*,$***$**$*+$*,$**$*,
$***$**$**$*+$*/$*){print
pack(chr$**$**$**$**$**$*
+$**$*+$*/$*-$*,$_[$_]);}

こんなことして遊んでいる方とかいますか?
いたら是非あなたの作品を見せてください。
0164名無しさん@お腹いっぱい。2001/08/06(月) 00:10ID:oWP36vTo
プログラミングPerlの初版って赤色?
改訂(日本語)は青だよね?
0165名無しさん@お腹いっぱい。2001/08/06(月) 00:11ID:???
ごめんなさい。
参考書スレッドがありました。
そっちにコピペします。
0166名無しさん@お腹いっぱい。2001/08/06(月) 12:33ID:???
>>163
うーん、その手の話題はプログラム板とかのほうが食いつきがいいんでは?
回文プログラムとかトリッキーなプログラムとかのスレあるし。
0167名無しさん@お腹いっぱい。2001/08/09(木) 03:07ID:bI3E6lI.
cpan2 どうなっちゃってるのかな。
http://www.cpan2.org
http://www.cpan2.com
0168名無しさん@お腹いっぱい。2001/08/13(月) 14:23ID:???
2chのdatとかの<>区切りのデータを切り分けるときって、
my ($name, $mail, $date, $contents) = split /<>/, $line;
ってやるよりも
$line =~ /(.*?)<>(.*?)<>(.*?)<>(.*?)/;
my ($name, $mail, $date, $contents) = ($1, $2, $3, $4);
ってやったほうが速いんですね。
見やすい、書きやすい以外のsplitを使う理由があれば教えてください。
また、もっと速い方法があるならばそちらも教えていただけませんか?
0169名無しさん@お腹いっぱい。2001/08/13(月) 15:27ID:???
>168
嘘はいけません。
my ($name, $mail, $date, $contents) = split /<>/, $line;
こっちの方が圧倒的に早い。
データ量によっては、
my @data = split /<>/,$line;
の方が早い。
my は付けない方が早い。

ちなみにスレ違い。このような話題は初心者コーナーへ。
0170名無しさん@お腹いっぱい。2001/08/13(月) 17:00ID:???
>>169
別に嘘を言いたかったわけではなくて、
use Benchmark;
my $line = "name<>mail<>date<>contents";
timethese(100000, {
foo => sub { my ($name, $mail, $date, $contents) = split /<>/, $line },
bar => sub { $line =~ /(.*?)<>(.*?)<>(.*?)<>(.*?)/;
my ($name, $mail, $date, $contents)= ($1, $2, $3, $4); }
});
ってやったときに、barの方が速いという結果が出たから質問したんですが・・・・
これは何故ですか?

あと、どこまでが初心者コーナー行きかの線引きがわかりません。
私としては、初心者コーナーはリファレンスを引けばわかるようなことを
やるところだと思っていたのですが。
0171名無しさん@お腹いっぱい。2001/08/13(月) 17:38ID:???
>>168 >>170
use Benchmark;
my $line = "name<>mail<>date<>contents";
timethese(100000, {
bar => sub { my ($name, $mail, $date, $contents) = split /<>/, $line },
foo => sub { $line =~ /(.*?)<>(.*?)<>(.*?)<>(.*?)/;
my ($name, $mail, $date, $contents)= ($1, $2, $3, $4); }
});
ってやったときに、barの方が速いという結果が出るのですが、
何故だか分かりますか?(>>170 のfooとbarを入れ替えている)

>>初心者コーナーはリファレンスを引けばわかるようなこと
まさしく貴方は初心者コーナーへどうぞ。
0172名無しさん@お腹いっぱい。2001/08/13(月) 19:51ID:???
foo => sub {
my ($name, $mail, $date, $contents) = split /<>/, $line
},

bar => sub {
$line =~ /(.*?)<>(.*?)<>(.*?)<>(.*?)/;
my ($name, $mail, $date, $contents)= ($1, $2, $3, $4)
}
#-----------------------#
Benchmark: timing 100000 iterations of bar, foo...
bar: 12 wallclock secs (10.19 usr + 0.00 sys = 10.19 CPU) @ 9817.40/s (n
=100000)
foo: 7 wallclock secs ( 5.93 usr + 0.00 sys = 5.93 CPU) @ 16866.25/s (
n=100000)
0173名無しさん@お腹いっぱい。2001/08/15(水) 00:30ID:???
# なんの役に立つかは知らんけど、SelectSaverのopen版
# どうでっしゃろ。
package OpenSaver;

use strict;
use Carp;
use Symbol;

use constant SAVE_FH    => 0;
use constant ARG_FH    => 1;
use constant OPEN_MODE    => 2;

my $pkg = __PACKAGE__;
sub new{
    
    my $class = ref($_[0]) ? ref(shift) : shift;
    @_ or croak("$pkg: usage $pkg->new(opned-FileHandle, file[, mode]");

    my($fh, $file, $mode) = @_;

    $mode ||= do{ $file =~ s/^([+<>]+)//; $1 || '<'};
    my $self  = bless [
            gensym(),
            qualify_to_ref($fh, caller),
            _open_mode_string($mode)
        ], $class;

    open $self->[SAVE_FH], "$self->[OPEN_MODE]&" . fileno($fh) or croak("$pkg: open error:$!");
    open $self->[ARG_FH],  "$mode$file" or croak("$pkg: open error:$!");

    return $self;
}
sub DESTROY{
    my $self = shift;
    open $self->[ARG_FH], "$self->[OPEN_MODE]&" . fileno($self->[SAVE_FH]);
}

sub _open_mode_string {
    my ($mode) = @_;
    $mode =~ /^\+?(<|>>?)$/
      or $mode =~ s/^r(\+?)$/$1</
      or $mode =~ s/^w(\+?)$/$1>/
      or $mode =~ s/^a(\+?)$/$1>>/
      or croak "$pkg: bad open mode: $mode";
    return $mode;
}
1;
__END__
#usage
use OpenSaver;
{
my $opensaver = new OpenSaver(STDOUT, 'test.txt', 'w') or die $!;
print "This is test.txt\n";
}
print "This is display\n";
0174名無しさん@お腹いっぱい。2001/08/16(木) 00:03ID:???
今過去ログ読み漁ってたんだけど>>10のって面白いね。
自分でも色んなコマンドもどき書いてるんだけど全然違います(-▽-;
モジュールの使い方とか参考になるなぁこれ、
0175恥ずかしながら2001/08/17(金) 01:35ID:???
正直、自分はPerl本に赤ラクダしか持ってないのであります。
それ故、オブジェクト指向的な書き方が未だに分からないのであります。
自分の書くコードはPerl4とPerl5がイビツに混じっているのであります。

逝ってよしでありますか?
0176名無しさん@お腹いっぱい。2001/08/17(金) 10:43ID:xrVq7k..
>>175
日本のPerlを書く人(というかCGIを書くのにPerlを使ってるヒトか)の9割方(感覚値)がそんな感じだろうから気にしないでいいよ。
裾野が広いから色々在るのは当然。んでもそのままだと、恥ずかしい思いをすることも在るので Effective Perlや perldoc perlstylを一読することを激しくお勧め。

http://www.ascii.co.jp/books/detail/4-7561/4-7561-3057-7.html
http://www.kt.rim.or.jp/~kbk/perl5.005/perlstyle.html
0177名無しさん@お腹いっぱい。2001/08/19(日) 02:16ID:i6ZuuVgY
PerlOSってどうなったんデシか?
0178名無しさん@お腹いっぱい。2001/08/19(日) 02:36ID:???
いや流石にPerlでOSは…(ワラ
コンパイル可能(?)なPerl6でなら…誰かやるのかねぇ。
0179名無しさん@お腹いっぱい。2001/08/19(日) 02:43ID:???
>>178
カーネルとPerl処理系のみで、システムは全てPerlで書くとか。
ダメかなぁ。知識0厨房でスマソ。
でもこれだったらスゴック小さい&軽いOSができそうだけどなぁ。
0180名無しさん@お腹いっぱい。2001/08/19(日) 03:54ID:???
>>179
軽くはないでしょう・・
0181sage2001/08/19(日) 16:15ID:i6ZuuVgY
>>177
http://www.perl.org/
0182恥ずかしながら1752001/08/20(月) 04:52ID:???
>>176
ありがとうであります。
新しい書き方も取り入れて行こうと思う次第であります。
018311101/08/27 09:56ID:gtVoupko
>>111
すみません、誤爆です。
逝ってきます。
018418301/08/27 10:08ID:cCFTKgE6
>>183
すみません、誤爆の謝罪を誤爆してしまいました。
申し訳ない。
0185名無しさん@お腹いっぱい。01/09/05 16:01ID:8Hg/qZ8I
プロンプト表示して逐次処理するのってどうするんでしょうか
Cのgetchar みたいなんすけど、、ARGV??
つーかプリント文が流れて逝くだけだし、、、俺ってあほですか?
0186名無しさん@お腹いっぱい。01/09/05 16:09ID:dfrFd246
>>185
うん。

#!perl
use constant PROMPT => '( ´∀`)>';
print PROMPT;
while (<>) {
    chomp;
    system $_;
    print PROMPT;
}
__END__
0187名無しさん@お腹いっぱい。01/09/05 17:09ID:jg.i3l1M
ぐはあ、STDINだたのか  (痴
逝って来ます    アホだ。。。
0188名無しさん@お腹いっぱい。01/09/06 20:41ID:???
File::statとかTime::localtimeとかFile::chdirみたいに
組み込み関数をかなり違う動作をする関数でオーバーライドするのってどうよ?

$s = new File::Stat('foo);
$t = new Time::Localtime(time);
$c = new ChdirSaver ('..');

などの方が読みやすく安全だと思うのだが。
0189名無しさん@お腹いっぱい。01/09/07 11:56ID:.xfvPVkw
>>188
同感。普通のコード書く時はそうですよね。
ただワンライナーを書く時はオーバーライドしてくれた方が便利という背景もある。
@EXPORT じゃなくて @EXPORT_OK に書いてくれてれば良いのにね。
0190名無しさん@お腹いっぱい。01/09/07 14:36ID:BHawRKfc
別にオーバーライドさせたくなければできますよ。
use File::Stat ();
@EXPORT に入ってるのはあくまで「デフォルト」でEXPORTするだけです。
空リストをuseに渡せばOK。
$st = File::stat($file);
019118801/09/07 18:42ID:???
>>190
そりゃそうだが、デフォルトでエクスポートするのが気に入らん、って事。
だからどうしたと言われりゃそれまでだが。
0192名無しさん@お腹いっぱい。01/09/08 00:16ID:TqV0GOBs
なるほど。
組み込み関数の名前をオーバーライドするってのは、
こんな使えない組み込み関数は捨てちまえ!俺のモジュール使え!という
モジュール作成者の自信をあらわすものだったりして。
0193名無しさん@お腹いっぱい。01/09/08 23:45ID:UUPZ4HXg
TERM:capの使い方教えれ。
0194名無しさん@お腹いっぱい。01/09/09 16:18ID:???
今コマンドみたいなのを色々書いてるんですが、入力の受け取りで困ってます

cp ./tmp/hoge './tmp/h u" g a' "./tmp/target'dir"
こう言う入力がSTDINから有ったとして、これを上手に

@argment = ('./tmp/hoge','./tmp/h u" g a','./tmp/target'dir');
つまりShellに与えた時の引数の解釈と同じ動作がしたいのです。

正規表現で削ってみたりと苦戦してみたのですが、引数の数は不定な事も
有って完全にShellと同じ動きをするのは不可能な気がしています。
今は1byteづつ積み上げて解釈するしかないのかなと思ってます。
参考になるソースなんかは無いでしょうか。出来ればperlなら感激なんですが
よろしくお願いします。
019519401/09/09 16:31ID:???
ちょっと説明が変ですね、perlshell.plを起動するとそこから
処理モードに入るんです、各コマンドのサブルーチンは大体出来ていて
例えば、
$./perlshell.pl cp ./tmp/hoge './tmp/h u" g a' "./tmp/target'dir"
こんな感じなら上手く行くのです(シェルが綺麗に@ARGVに収めてくれるので)
ところが$./perlshell.pl として起動して
perlshell$←入力待ち
cp ./tmp/hoge './tmp/h u" g a' "./tmp/target'dir"
とした時の<STDIN>からの入力の処理が出来ないのです。
ここに
0196名無しさん@お腹いっぱい。01/09/09 16:40ID:???
>>194
もう少しマトモかつ具体的な例を頼む。
019719401/09/09 17:08ID:???
すいません、>196
つまりShellをエミュレートしたいのだと思います。
tcshから、./perlshell.pl とタイプすると
perlshell$ こう言うプロンプトが出ます。
そこに
cp "dist1" "dist2" "dist3" "target" と入力した時の
<STDIN>からの入力を上手に配列(上なら("dist1","dist2","dist3","target"))
に収めたいのです。
今bashのソースを拾ってきたのですが、何故か心が重いです・・・
0198名無しさん@お腹いっぱい。01/09/09 18:08ID:???
それなら><|等の処理もした方が良くないか?
と思いつつ少し考えてみる。

とりあえず
http://www.din.or.jp/~ohzaki/perl.htm#Tag_Remove
でも読みながら考えていろ。
019919401/09/09 21:46ID:???
ありがとう御座います、>198
シェルのソース見てみたんですが、Cが殆ど読めないので良く分かりません
でした、ただそれらしきループが有ったんでやはり1byteづつ切り出してる
んだと思います。

取り合えずsubstrで1byteづつ切り出してるんですが、難しいです。
フラグだらけで訳が分からなくなってきた。
まずは ' の中では " が使える、" の中では ' が使える。
これを目指して頑張ってます。
パイプとリダイレクトはどうしようかなぁ、何か無理っぽいです。
0200名無しさん@お腹いっぱい。01/09/09 21:53ID:NKqI5UNo
$cmd = <SHIFT>;
print `$cmd`;
で

$ perlshell rm -rf /

じゃだめなの?
020119801/09/09 22:18ID:???
ダメだな。折れ力じゃ無理らしい(鬱
逝ってきます。
#!perl
my $command = q{cmd>foo.txt "double quote" '/single quote/' "cmd>foo.txt"};

print Dumper [parseline($command)];

sub parseline{
my $str = shift;
my $quoted_str = qr{(?:[^"' ]|"[^"]*"|'[^']*')*};
my $i = 0;
return grep{ $i++ % 2 }(split /($quoted_str)/o, $str);

}
__END__
0202JAPU@ページデザイン変更してみたり01/09/09 22:35ID:???
こうしとけ。(笑)

$arg = q/Sakura "Moe" "\"puni\"" 'hanya-n'/;
@arg = split /\0/, `perl -e 'print join "\\0", \@ARGV' $arg`;
print "$_\n" foreach @arg;
0203>>JAPUさん01/09/09 22:53ID:???
ご丁寧にバナーまでモノクロにしてある(笑
でもあまり暗いのは好きじゃないですね。鬱になりそう。
0204名無しさん@お腹いっぱい。01/09/09 23:32ID:???
>>194
psh (Perl Shell) っていうのがあるらしいんだが、参考にはなるか?

ttp://sourceforge.net/projects/psh/
020519401/09/10 01:25ID:???
わわ、JAPUさんまで、感謝です>みなさん
>>200 それはちょっと・・(笑

>>201
いえいえ、凄く参考になります。自分では何も思いつかないレベルなので

>>202
凄いトリックですね、こんなの絶対考えつかないです。
今回は、勉強がてらなるべくシステムを呼ばない前提なので、
最後の手段に保存させてもらいました。

>>204
大感謝です、これは凄い。
入れてみてビックリしました、完全にShellの動作をしてます
グロビングまで自前でやってる様です、きっとこの人は偏執狂だ(笑
同じ名前で情けないので dameshell に改名しました。
今、該当部分を探している所です。段々流れがつかめて来た気がします。
今日は寝るので、ある程度形になったらまた報告させてもらいます。

多謝です>みなさん
0206 01/09/10 07:13ID:???
while( $arg ){
$arg =~ s/^\s*//;

if( $arg =~ /^"/ ){
if( $arg =~ s/^"((\\.|[^"])*)"// ){ push @args, &parse_meta( $1 ) }
else{ die "unmatched" }
}
elsif( $arg =~ /^'/ ){
if( $arg =~ s/^'([^']*)'// ){ push @args, $1 }
else{ die "unmatched" }
}
elsif( $arg =~ /^`/ ){
if( $arg =~ s/^`((\\.|[^`])*)`// ){ push @args, &parse_command( $1 ) }
else{ die "unmatched" }
}
elsif( $arg =~ s/^(\S+)// ){
push @args, &parse_meta( $1 );
}
else{
last;
}
}

うーん。この位なら正規表現一発で綺麗に書けそうだけど…
リダイレクトやパイプがないんじゃシェルとは…
0207名無しさん@お腹いっぱい。01/09/10 10:19ID:7tqUQO.2
んー shellと同じように分割したいなら標準モジュールの Text::ParseWords つかえば良いのに。

#!perl
use Text::ParseWords;
@args = shellwords($strings);
__END__
020819401/09/10 15:53ID:???
#**********************************
use strict;

&Main_block;
sub Main_block{
    my ($input,@output,$count);
    print "ひき数をいれてください\n";
    $input = <STDIN>;
    @output = &Parse_arg($input);
    $count = 0;
        foreach (@output){
            print '$ARGV'."[$count]\t$_\n";
            $count++;
        }
    exit;
}
020919401/09/10 15:54ID:2zI8oYIY

#***** 引数を解釈して配列に入れる
sub Parse_arg{
    my ($input,$charnum,$char,$argpart,$count,$quot_flag,@out);
    $input = shift;
    chomp ($input);
    $charnum = length ($input);
        while ($count < $charnum){
            $char = substr ($input,$count,1);
            if (($char eq ' ')&&(!$quot_flag)){
                $char = '';
                    if ($argpart){push (@out,&Unquote($argpart))};
                $argpart = '';
            }
            elsif ((($char eq '\'')||($char eq '"'))&&(!$quot_flag)){
                $quot_flag = "$char";
            }
            elsif (($char eq $quot_flag)&&($quot_flag)){
                $quot_flag = '';
            }
            if ($count == (${charnum}-1)){
                $argpart .= $char;
                if (&Unquote($argpart)){push (@out,&Unquote($argpart));}
            }
            $argpart .= $char;
            $count++;
        }
    return (@out);
}
#***** クオートを取り去る
sub Unquote{
    $_ = shift;
    $_ =~ s/^\'([^\']*)\'$/$1/;
    $_ =~ s/^\"([^\"]*)\"$/$1/;
    return $_;
}
#**********************************
021019401/09/10 15:57ID:???
こんにちは、またまた有難うございます、勉強になります

>>206
いえいえ、**完全に**とか言ってしまいましたが、本当は
It's my dir と言うディレクトリを開けなかったのと不定な
引数の数に対応出来なかっただけなのです。 " の中では ' が
使える、逆もOK、"と' の中ではスペースが使える、区切り文字の
スペースは幾つでも良い。これ位が目標だったので
リダイレクトは本物の動作がよく理解出来てない厨房っぷりなので
今後の課題にしようと思います。

>>207
知らなかったです、>>204さんに教えて頂いたpshもそうでしたが
細かく機能別のサブルーチンに分けて、そこに投げて行くんですね。
今、sub parse_lineとにらめっこしてます。実は、モジュールはrootに
有るの位しか使った事が無いのです(汗)

恥かしいコードですが結果、上の様になりました。
本物のふるまいが理解出来てないので今一つですが、
一応目的は達しました。ループしてるのは効率的じゃないかも、、
まだ比較演算子の優劣が分からないのでカッコだらけですが
ご勘弁ください、変な所有ったら指摘してもらえたら嬉しいです。
ありがとうございました>みなさん。 ホント勉強になる!
この板は2chじゃないですよね 笑)
0211名無しさん01/09/10 18:00ID:???
プライオリティも解らんのにこんなの書けるのかよ(´Д`;)
0212超上級者01/09/13 05:28ID:???
あるファイルシステムがマウントされているかどうかをPerlから知るにはどうすればいいのかね?
それと、実行されている環境のバイトオーダーを知る方法は?

知ってる人はココに書きなさいね。
0213_gunzip01/09/13 05:59ID:???
#!/usr/bin/perl -w

use Inline C;

our @filesystems = ("/dev/sda1", "/dev/fd0", "/dev/cdrom");

foreach my $fs (@filesystems){
    print "$fs: ", is_mounted($fs) ? "mounted\n" : "not mounted\n";
}

__END__
__C__
#include <mntent.h>

#define TABLE_FILE "/etc/mtab"

int is_mounted(char *fsname)
{
    FILE *fp;
    struct mntent *ent;

    if((fp = setmntent(TABLE_FILE, "r")) == NULL)
        return -1; /* error */

     while((ent = getmntent(fp)) != NULL){
        if( !strcmp(ent->mnt_fsname, fsname) )
             return 1; /* found */
     }

    endmntent(fp);
    return 0; /* not found */
}
0214_gunzip01/09/13 06:03ID:???
#!/usr/bin/perl

use Inline C;

sub is_little_endian2()
{
    return pack("I", 1) eq pack("V", 1);
}

sub is_little_endian3()
{
    return vec(pack("I", 1), 0, 1);
}

__END__
__C__

int is_little_endian1()
{
    union {
        int val;
        char byte[sizeof(int)];
    } u;
    u.val = 1;
    return u.byte[0] == 1;
}
0215超初心者01/09/13 06:04ID:???
-eでいいんじゃねーの?

unpack('s', pack('n',1));
戻り値で判断
0216_gunzip01/09/13 06:13ID:???
せっかくなのでInlineモジュール使ってみました。

#このスレッドに書き込むのも久しぶりな気がする...。
#いつの間にか書き込み200を越えていて嬉しひ。
0217名無しさん@お腹いっぱい。01/09/13 09:16ID:FCaipOx6
NFSかどうかを知るにはどうすればいいんですか?
flockが使えないなら、自動的に他のロックを使いたいのです。
0218名無しさん@お腹いっぱい。01/09/13 12:59ID:skA46.9M
>>217
/etc/mtabの中をみて、マウントタイプ判断すればいいんじゃない?
うちの環境になぜか入っていた Quota モジュールを使う手も。

use Quota;
print is_nfs(/home2/john/path) ? 'Danger!' : 'Safe';

sub is_nfs {
  my $path = shift;
  my $is_nfs = 0;
  Quota::setmntent();
  while (my @mntent=Quota::getmntent()) {
    if( $path ~= /^$mntent[1]/ and $mntent[2] eq 'nfs'){
      $is_nfs = 1;
      last;
    }
  }
  Quota::endmntent();
  return $is_nfs;
}

flockが使えないファイルシステムは他にもあるでしょうから、
もっと調べないとダメだと思いますけどね。
CfgTie::TieMTab っていうモジュール使うと便利かも。
021921801/09/13 13:03ID:???
あ、is_nfs('/home2/john/path') ね、言うまでもないけど。
0220_gunzip01/09/13 15:42ID:???
お、Quotaという便利なモジュールがあるんですね。勉強になります。

ちなみに、マウントされたファイルシステムのタイプ(nfs, ext2, msdos, etc...)を取得するには
mntent構造体のmnt_typeメンバを調べるだけでおっけいです。

--> getmntent(3), fstab(5)
#213のは、見つかった場合endmntent(FILE *)を呼ぶのを忘れてる...。
0221名無しさん@お腹いっぱい。01/09/13 16:18ID:???
>>217 eval使って返値でチェックしたら?
0222JAPU@会社作ったにょ01/09/13 16:47ID:???
NFSでも、flockは成功するにょ。
ただ、NFS だとうまくロック出来ない場合がある... らしい。

# 何種類佳乃組合わせでためしたけど、全部成功したので "らしい" としか...
022321701/09/14 13:09ID:???
みなさんどうも。

eval { flock(STDIN) };
if ($@) {
 # my_flock
}
elsif (is_nfs("mypath/mylockfile") {
 # my_flock
}
else {
 # flock
}

てな具合でいきたいと思います。

>>222
># 何種類佳乃組合わせでためしたけど、全部成功したので "らしい" としか...
成功したっていうのは吐いた制御がちゃんとできているってことですか?
# 自分も実験できる環境がないので "らしい" でしかないんですよね。
0224名無しさん@お腹いっぱい。01/09/14 13:22ID:???
flock(STDIN)は常にdieすると思うのだがどうかな?
0225名無しさん@お腹いっぱい。01/09/14 13:27ID:???
218の is_nfs に相対パスを渡しても、うまくいかないと思う。
0226名無しさん@お腹いっぱい。01/09/14 17:56ID:???
あたりまえ。
022722601/09/14 18:07ID:???
すまん。マジ誤爆。
0228名無しさん@お腹いっぱい。01/09/14 23:38ID:???
>>222
美凪組み合わせだとどうですか?
022921701/09/15 01:07ID:???
修行のためCPANのLock関連のモジュールあさってたけど、
NFSの自動判別とかしないでユーザに指定させるか、
flockは完全に無視して独自ロックだけをつかう方法が多かった
前者がLockFile::Simple、後者がFile::FlockDir、File::NFSLock

厨房は厨房らしく自動判別はやめて、ぬるく逝こうと思う。
0230PerlHacker01/09/19 05:33ID:???
ここにはすごそうな人が多そうなのでここで聞きます。
ページを見ている人のパソコンのCD-ROMを排出させる方法をCGIでやるやり方を教えてください!!!!
ネットを探しまわったのですが見つかりませんでした。
0231名無しさん@お腹いっぱい。01/09/19 05:45ID:???
>>230
そいつの家まで逝って、手動で開けてやれ。
■ このスレッドは過去ログ倉庫に格納されています