翻訳:「Perl FAQ 翻訳グループ」
同メンバ:
樋口さん、上原さん、高田さん、関谷さん、妻鹿さん、三島
------------------------------------------------------------------------------
Stephen P Potter Pencom Systems Administration AMP Incorporated
spp@peach.epix.net spp@psa.pencom.com steve.potter@amp.com
Home: 717-540-0131 Pager: 1-800-759-8888, 547-9561 Work: 717-986-5401
Systems Administation: It's a Kind of Magic
------------------------------------------------------------------------------
--
Archive-name: perl-faq/part4
Version: $Id: part4,v 2.9 1995/05/15 15:46:10 spp Exp spp $
Posting-Frequency: bi-weekly
Last Edited: Wed Aug 16 21:22:18 1995 by spp (Stephen P Potter) on temples.syrix.com
4.1) W$@%*<> という記号は何なのですか、またこれはどんな時に使う物なのかどうしたらわかりますか?
4.2) どうしてPerlの演算子はCの演算子と違った優先順位となっているのですか?
4.3) 動的および静的(レキシカル)スコープの違いは何ですか? my() と local() の違いは何ですか?
4.4) ディープおよびシャローバインディング違いは何ですか?
4.5) 固定長レコードファイルを操作するにはどうすればいいですか?
4.6) サブルーチンに対してローカルなファイルハンドルを作るには どうすればいいですか?
4.7) 1秒以下で sleep あるいは alarm をするにはどうすれば いいですか?
4.8) Perlでは atexit() や setjmp()、longjmp() を どうやっておこなうのですか? (例外処理)
4.9) perlではどうやってsignalsをcatchするのですか?
4.10) どうしてPerlは私の8進数データを8進数として 解釈しないのですか?
4.11) 2つの日付の文字列を比較するにはどうしたら いいでしょうか?
4.12) ジュリアン日を見つかるにはどうしたらいいですか?
4.13) perlには round関数がありますか? ceil()とfloor()についてはどうですか?
4.14) perlで与えられたタスクを書き上げるための最も早いやり方は 何ですか?
4.15) Do I always/never have to quote my strings or use semicolons?
4.16) What is variable suicide and how can I prevent it?
4.17) What does "Malformed command links" mean?
4.18) How can I set up a footer format to be used with write()?
4.19) Why does my program keep growing in size?
4.22) How can I quote a variable to use in a regexp?
4.23) How can I change the first N letters of a string?
4.24) How can I count the number of occurrences of a substring within a string?
4.25) Can I use Perl regular expressions to match balanced text?
4.26) What does it mean that regexps are greedy? How can I get around it?
4.27) How do I use a regular expression to strip C style comments from a file?
4.28) How can I split a [character] delimited string except when inside [character]?
4.29) どうして "local($foo) = <FILE>" はうまく機能しない のですか?
4.30) How can I detect keyboard input without reading it?
4.31) How can I read a single character from the keyboard under UNIX and DOS?
4.32) How can I get input from the keyboard without it echoing to the screen?
4.33) Is there any easy way to strip blank space from the beginning/end of a string?
4.34) How can I output my numbers with commas added?
4.35) 文字列の中でタブを拡大するにはどうしたらいいのですか?
4.36) voidコンテキスト中におけるgrep() あるいは map() の使用は どこがよくないのですか?
これらは型指定子です。:
$はスカラ変数
@はインデクス配列
%はハッシュ配列(連想配列)
*はそのシンボル名の型すべて。これらはperl4では時折ポインタのように使われていましたが、perl5では参照を使用します。
<>はファイルハンドルからレコードを入力するのに使われます。
\はあるものへの参照の意味です。
Perlのポインタについてもっと知りたい時は、配列の配列という質問を参照してください。
ファイル関連を除いて、これらの型指定子を特に必要としない個所も結構ありますが、これらは常用したほうがいいでしょう。但し、
人々はしばしば次のように要望します。:
:perlの文法をもっと awk や C のように変更したらどうでしょうか?
そうはいってもシェルほどひどくはないでしょう。 :-)
Perl 5では不必要な句読点から脱却するために私がずっと頑張ってきたことを知ったら
うれしいと感じることでしょう。$や@のような名詞マーカは不要ではないと考えているとわかると面白くないかもしれません。
それらは人間の言葉の中でcaseマーカがしているのと同様に機能しているばかりでなく、
挿入されたコンテキスト中で自動的に判別されるのです。ですから、
あるコンテキスト内ならこうで、その外ならこうと、変数を参照する為に異なった文法上の処理をしなければならないと、利用者がいちいち心配する必要はないのです。
しかし、動詞の前置詞 & は、ちょうど"do"が英語にあるように、現在オプショナル
です。私が言っていることを十分理解していただいているようにと切に願っています。
例えば、よく次のように記述していたとします。:
(前述したシェルのようなinterpolativeな理由のため)各名詞節の前にマーカを
引っぱり出すことは、Perlでは実に都合の良いことでした。大半の方はそんな
やり方を好んでいるように思えます。BASICの多くの変数がやっているように、
それらを末尾に置くよりも、この方がずっとわかりやすいと確かに思えるのです。
実際には、そうではありません。;Perlの中でも、全てのC演算子はCの中で行っているのと同様の優先順位を持っているのです。問題は、print、chdir、exec、system等々のリスト演算子と呼ばれる機能のクラスがあることです。
それらは、右側にあるか左側にあるかで異なった優先順位を持つものの中でも、
一風変わったものなのです。
基本的には、それらは全てのものを右側にまとめあげます。例えば、
さらに殺人的な詳細については
perlop(1) man ページの優先順位の項を参照してください。
そして、このようなことを捕捉するために、必ず -w フラグを使用するように
してください。
知っておかなければならない最重要点は、Perlの $、 @、%、および & が
Cの *演算子に味付けをしたバージョンだと考え始めているとしたらちょっとまずい
ことになっているということです。あなたがそれらが演算子であると考えていても、
実際には演算子ではありません。Cでは、
[注意:この質問はperl5だけに関するものです。perl4にはmy()はありません。]
おっと、レキシカル変数はperl5でのみ有効です。アップグレードを考えた方が
いいですよって、まだ言ってませんでしたっけ?:-)
5.000 向け回答:
これは自分自身のサブルーチンを作っているとき、少なくともその程度の状況で
のみ問題になるものです。以下はシャローバインディングについて理解をする
助けとなるでしょう。
5.001 向け回答:
perlは常に関数へのディープバインディングを与えます。ですから、もはや
evalハックは必要ありません。さらに、別のレキシカルスコープ内でネスト
された関数そしてレキシカルに宣言されたフォーマットもそのスコープへの
アクセスができます。
最も効率的な方法はpackとunpackを使うことです。
これはsubstrを使うよりも高速です。
この事例ではpsから固定様式の入力行を分解し、再度一緒に戻すという
コードの一端のサンプルを下記に示します。
型グローブである*VAR表記を使わなければなりません。
下記は、ネストされたローカルな
includeファイルに対し,自分自身を再帰的にcallしながらincludeファイルを
catするコードです。
(注:#include <file>ではなく、#include "file"となっているものが対象)
もし(usleep()が提供するような)1秒以下の精度がお望みで、システム上に
itimers と syscall()があるのなら、次のように使用することができます。
また、select()を使うこともできるはずです。
SIGALRMを受け取るまでどの位の遅延があったか示す浮動小数点数を取り、
以前のタイマに残り時間があればどの位あったのかを示す浮動小数点数を戻します。
Cの関数では整数を使用しますが、これは有理数(分数)であるかどうかは
気にしてませんのでその点留意して下さい。
Perlの例外処理機構がそのeval演算子です。
(Perl's exception-handling mechanism is its eval operator. )
setjmpとしてevalを、logjumpとしてdieを使用できます。
下記はLarryのタイムアウト入力用のサンプルです。Cではよくsetjumpとlongjumpを
使って実装されています。
Perl5では、パッケージ毎のEND関数の自動処理のおかげでこれを設定するのは
簡単です。これらはawkであるかのように機能します。
perlfunc(1)、
perlmod(1)、
perlrun(1)を参照。
evalはまた、symlinksのようにシステムに依存した特徴をテストしたり、
一方であなたをかんかんに怒らせるような
ユーザ入力の正規表現を使ったりするにはほんとうに便利です。
(using a user-input regexp that might otherwise
blowup on you)
Perlは%SIG連想配列を使ってシグナルをtrapすることを認めています。
trapしたいシグナルをキーとして使って、そのシグナルへ
サブルーチンを割り当てることができます。
%SIG配列は、プログラマが定義したそれら変数を含んでいるだけです。
たとえば、^Cからはっきりとexitするには:
5.001では、$SIG{__WARN__} と $SIG{__DIE__}ハンドラはdie()とwarn()を
インターセプトするのに使用されるかもしれません。
たとえば、下記は、単なる文句(complaining)レベルというより致命レベルで
トリガすべき初期化していない変数をpromoteするやりかたです。
Perlは8進数と16進数があなたのプログラムの中でリテラルとして発生した時は
単にそのまま理解します。
それらがどこからか読み込まれ、割り当てられた場合は、自動変換は起きません。
この種のことを起こしたいのなら明示的にoct() あるいはhex()を使用しなければ
なりません。
実際には、oct()は8進数と16進数の両方とも解釈することを知っており、
一方hexは16進数と10進数の変換をするだけです。たとえば:
もし10進数、8進数と16進数の入力を処理するものが要るのなら、
manページの中の提案にしたがって、それを使うすることもできます。
その日付が簡単に構文解析できる予め決められた形式なら、それを
バラバラにして構成部品化したり、配布されているperlライブラリの
&timelocalをcallすればよいでしょう。しかしながら、日付の文字列が
形式不定の場合は、Cnews配布のgetdateプログラムを使う方が多分簡単
でしょう。これは幅広い日付の形式を受け付けます。
どちらの場合も、実際に比較すべき戻り値は、time()によって戻される
ような合計秒数となっていることに留意して下さい。
下記はあまり効率のよくないperl用getdate関数です。;
一度に複数の日付を送るようにしたり、pipeでよりよく振る舞うように
getdateを修正したりして、これを改良することが可能です。
実際には、Richard Ohnemus <Rick_Ohnemus@Sterling.COM>が
Perl yaccと共に使用する getdate.y を持っています。
( 3.3 perl のための yacc はありますか?
参照)
下記はThomas R.Kimpton* から提供されたジュリアン日関数の例です。
Perlには明示的なround関数はありません。しかしながら、丸め関数を
生成するのは非常に簡単です。int()関数は単純に小数値を取り除き、
整数部を戻すので、以下のものを利用できます。
もう少し改良した解決法は、同じように負数を処理するもので、(上記の)
戻り値に変更を加えたものになるでしょう。
特定の重要な桁までまるめたいと思った場合、printf関数(あるいはsprintf、
状況によります)を使うことができます。
それは自動的に適切なまるめを行います。(s)printf関数についての詳細な情報は
perlfunc manページを参照してください。
バージョン5は標準C数学ライブラリ関数を定義しているPOSIXモジュールを含んでおり、それにはfloor() と ceil()も含まれています。
floor($num)は$num以下で最大の整数を戻し、ceil($num)は$num以上で最小の整数を
戻します。例えば:
それをcomp.lang.perl.miscに投稿し、それについての質問をTomかRandalに
尋ねなさい。;)
なぜならPerlは、いろいろな与えられたタスクに対して様々な異なったアプローチを
するのに非常に向いているため、与えられたタスクを書くための最も早いやり方は
何であるかというのは共通の質問となるのです。
アプローチのいくつかが他のものより劇的に効果的である可能性はありますから、
どれが最良の方法かを知るのは時には価値があることです。
不幸にも、たぶんCやシェルからの直接の書換のような最初に浮かんだ実装は、
しばしば次善のパフォーマンスをもたらします。
全てのアプローチが異なるハードウェアやソフトウェアのプラットホームで
同じ結果をもたらすわけではありません。
さらにスピードの為に読み易さを犠牲にしなければならないことがしばしばあります。
経験豊富なperlプログラマはコードをじっと見つめ、どのやり方が最も早いかに
関して経験に基づいた推測をしますが、どんでもないことはそれでも起こることが
あります。
ですから、経験主義的な科学であるperlプログラミングの精神において、
幾通りもの異なった方法のうちどれが最も早いかを見つける一番良いやり方は、単に
それらを全部書き上げて、それらの時間を計ってみることです。例えば:
4.15) Do I always/never have to quote my strings or use semicolons?
You don't have to quote strings that can't mean anything else in the
$SIG{INT} = Timeout_Routine;
@Days = (Sun, Mon, Tue, Wed, Thu, Fri, Sat, Sun);
but you can't get away with this:
$foo{while} = until;
in place of
$foo{'while'} = 'until';
The requirements on semicolons have been increasingly relaxed. You no
for (1..10) { print }
is ok, as is
@nlist = sort { $a <=> $b } @olist;
but you probably shouldn't do this:
because you might want to add lines later, and anyway, it looks
Actually, I lied. As of 5.001, there are two autoquoting contexts:
This is like this
4.16) What is variable suicide and how can I prevent it?
Variable suicide is a nasty side effect of dynamic scoping and the way
$x = 17;
Then you have just clobbered $_[0]! Why this is occurring is pretty
sub munge {
That doesn't help you if you're going to be trying to access @_
Another manifestation of this problem occurs due to the magical nature
@num = 0 .. 4;
num begin 0 1 2 3 4
What's happening here is that $m is an alias for each element of @num.
The perl5 static autos via "my" do not exhibit this problem.
4.17) What does "Malformed command links" mean?
This is a bug in 4.035. While in general it's merely a cosmetic
4.18) How can I set up a footer format to be used with write()?
While the $^ variable contains the name of the current header format,
If you have a fixed-size footer, you can get footers by checking for
Another strategy is to open a pipe to yourself, using open(KID, "|-")
See the perlform(1) man page for other tricks.
4.19) Why does my Perl program keep growing in size?
This is caused by a strange occurrence that Larry has dubbed "feeping
Oh, wait... you meant a currently running program and its stack size.
An eval() which terminates in error due to a failed parsing will leave
A local() inside a loop:
for (1..100) {
will build up 100 versions of @array before the loop is done. The
local(@array);
This local array behaviour has been fixed for perl5, but a failed
One other possibility, due to the way reference counting works, is
sub oops {
When $x goes out of scope, the memory can't be reclaimed, because
Yes, you can, since Perl has access to sockets. An example of the rup
4.21) Why doesn't my sockets program work under System V (Solaris)? What
Some System V based systems, notably Solaris 2.X, redefined some of the
Note that even though SunOS 4 and SunOS 5 are binary compatible, these
Under version 5, you can also "use Socket" to get the proper values.
4.22) How can I quote a variable to use in a regexp?
From the manual:
$pattern =~ s/(\W)/\\$1/g;
Now you can freely use /$pattern/ without fear of any unexpected meta-
Perl5 provides a vastly improved way of doing this. Simply use the
4.23) How can I change the first N letters of a string?
Remember that the substr() function produces an lvalue, that is, it may
This assumes that $[ is 0; for a library routine where you can't know
substr($var,$[,1) = 'S';
While it would be slower, you could in this case use a substitute:
$var =~ s/^./S/;
$var =~ s/^[^\0]?/S/;
To do things like translation of the first part of a string, use
substr($var, $[, 10) =~ tr/a-z/A-Z/;
If you don't know the length of what to translate, something like this
/^(\S+)/ && substr($_,$[,length($1)) =~ tr/a-z/A-Z/;
s/^(\S+)/($tmp = $1) =~ tr#a-z#A-Z#, $tmp/e
although in this case, it runs more slowly than does the previous
4.24) How can I count the number of occurrences of a substring within a
If you want a count of a certain character (X) within a string, you can
$string="ThisXlineXhasXsomeXx'sXinXit":
This is fine if you are just looking for a single character. However,
$string="-9 55 48 -2 23 -76 4 14 -44";
4.25) Can I use Perl regular expressions to match balanced text?
No, or at least, not by themselves.
Regexps just aren't powerful enough. Although Perl's patterns aren't
while(<>) {
A rather more elaborate subroutine to pull out balanced and possibly
4.26) What does it mean that regexps are greedy? How can I get around it?
The basic idea behind regexps being greedy is that they will match the
For example, I recently came across something like this:
$_="this (is) an (example) of multiple parens";
This code was supposed to match everything between a set of
is
However, the backreference ($1) ended up containing "is) an (example",
In perl4, the way to stop this from happening is to use a negated
while ( m#\(([^)]*)\)#g ) {
In perl5 there is a new minimal matching metacharacter, '?'. This
while (m#\((.*?)\)#g )
Hint: This new operator leads to a very elegant method of stripping
s:/\*.*?\*/::gs
4.27) How do I use a regular expression to strip C style comments from a
Since we're talking about how to strip comments under perl5, now is a
s#/\*[^*]*\*+([^/*][^*]*\*+)*/|([^/"']*("[^"\\]*(\\[\d\D][^"\\]*)*"[^/"'
C++ comments:
(Yes, Jeffrey says, those are complete programs to strip comments
4.28) How can I split a [character] delimited string except when inside
I'm trying to split a string that is comma delimited into its different
SAR001,"","Cimetrix, Inc","Bob Smith","CAM",N,8,1,0,7,"Error, Core Dumped"
Due to the restriction of the quotes, this is a fairly complex
undef @field;
4.29) どうして "local($foo) = <FILE>" はうまく機能しない
のですか?
Well, it does. The thing to remember is that local() provides an array
local($foo) = scalar(
4.30) How can I detect keyboard input without reading it?
You should check out the Frequently Asked Questions list in
sub key_ready {
Under perl5, you should look into getting the ReadKey extension from
4.31) How can I read a single character from the keyboard under UNIX and DOS?
A closely related question to the no-echo question below is how to
$BSD = -f '/vmunix';
$key = getc(STDIN);
if ($BSD) {
You could also handle the stty operations yourself for speed if you're
sub set_cbreak { # &set_cbreak(1) or &set_cbreak(0)
ioctl(STDIN,&TIOCGETP,$sgttyb) || die "Can't ioctl TIOCGETP: $!";
@ary = unpack($sgttyb_t,$sgttyb);
ioctl(STDIN,&TIOCSETP,$sgttyb) || die "Can't ioctl TIOCSETP: $!";
Note that this is one of the few times you actually want to use the
For perspectives on more portable solutions, use anon ftp to retrieve
Under Perl5, with William Setzer's Curses module, you can call
For DOS systems, Dan Carson
To put the PC in "raw" mode, use ioctl with some magic numbers gleaned
$old_ioctl = ioctl(STDIN,0,0); # Gets device info
Then to read a single character:
sysread(STDIN,$c,1); # Read a single character
And to put the PC back to "cooked" mode:
ioctl(STDIN,1,$old_ioctl); # Sets it back to cooked mode.
So now you have $c. If ord($c) == 0, you have a two byte code, which
# PC 2-byte keycodes = ^@ + the following:
# HEX KEYS
This is all trial and error I did a long time ago, I hope I'm reading the
4.32) How can I get input from the keyboard without it echoing to the
Terminal echoing is generally handled directly by the shell.
print "Please enter your password: ";
Again, under perl 5, you can use Curses and call &Curses::noecho() and
4.33) Is there any easy way to strip blank space from the beginning/end of
Yes, there is. Using the substitution command, you can match the
s/^\s*(.*?)\s*$/$1/; # perl5 only!
s/^\s+|\s+$//g; # perl4 or perl5
or even
s/^\s+//; s/\s+$//;
Note however that Jeffrey Friedl* says these are only good for shortish
For the longer strings, he suggests using either
$_ = $1 if m/^\s*((.*\S)?)/;
or
It should also be noted that for generally nice strings, these tend to
4.34) How can I print out a number with commas into it?
This one will do it for you:
sub commify {
$n = 23659019423.2331;
GOT: 23,659,019,423.2331
The reason you can't just do
s/^(-?\d+)(\d{3})/$1,$2/g;
Is that you have to put the comma in and then recalculate anything.
4.35) 文字列の中でタブを拡大するにはどうしたらいいのですか?
さて、正確ではありませんが、保守できるコードを書くにはいい方法では
ありません。
下記のように、ある答が欲しい時grepを使うのはただ立派なことです。
ほとんどのすべてのプログラムにおける最も重要なことは以下の順番の通りである
ことを銘記しておいてください。:
一方、JAPHs (aka Obfuscated Perl entries)を書いてみようとしていたり、
汚いコードを書いてみようとしている場合、多分以下のように逆になるでしょう。:-)
ホームページへ戻る。
こういうのはご存じですね。:
$foo = BAR;
これは、下記のように解釈されます。
$foo = 'BAR';
こんなふうには解釈されません。
$foo = <BAR>
もし文字列を引用符で囲む習慣があれば、こんなトラップは避けられます。
通常は、ファイルは下記のように何かしら操作されます。(それが生産コードとしたら適切なエラーチェックが付け加えられているでしょう):
open (FILE, ">/tmp/foo.$$");
print FILE "string\n";
close FILE;
ファイルハンドルの代わりにファイル操作機能と一緒に普通のスカラ変数を使えば、
ファイルハンドルへの間接的な参照と見なされます。例えば、
$foo = "TEST01";
open($foo, "file");
open後は、下記2つのwhileループは等価となります。:
while (<$foo>) {}
while (<TEST01>) {}
これら2つの記述も同様です。:
close $foo;
close TEST01;
しかし、これは違います。:
while (<$TEST01>) {} # エラー
^
^ 不正なドル記号に注目
次は、初心者が陥りやすいもう一つの誤りです。;
open($foo, "output.$$");
これは、しばしば $foo の値として代入されるのだろうと勘違いされます。
実際にはそうではありません。 open の操作の前に、ファイルハンドルの名前を$foo に
設定しておかなければならないのです。
$$mean @less $-signs <and> &other *special \%characters のことです。
I $$mean @less
: $-signs = <and> &other *special \%characters?
Larry の答えはこうです:
&california || &bust;
現在では下記のようにもっと明確に記述できるのです。:
california or bust;
もちろん厳密に言えば、$ と @ はcaseマーカではなくnumberマーカです。
英語は強制的な(mandatory) numberマーカを持っており、同意しない時人々は
混乱してしまうのです。
4.2) どうしてPerlの演算子はCの演算子と違った優先順位となっているのですか?
unlink $foo, "bar", @names, "others";
は、これら全てのファイル名を unlink します。一般的な誤りはこんな風に
書くことです。:
unlink "a_file" || die "snafu";
問題はこれが次のように解釈されることです。
unlink("a_file" || die "snafu");
この問題を避けるには、常にファンクションコールのようにみなして使ってしまうか、
括弧を外側につけて使用することです。:
unlink("a_file") || die "snafu";
Perl5では、優先順位の低い"and", "or", および "not"演算子があり、
これらはカンマより緩やかに結合します。これで下記のような記述をしても
いいようになりました。
:
(unlink "a_file") || die "snafu";
unlink $foo, "bar", @names, "others" or die "snafu";
時々は戻り値について、十分な注意を払いましょう。
:
unless ($io_ok = print("some", "list")) { }
そうです、print() は I/O の成功を戻します。ということは、
$io_ok = print(2+4) * 5;
は、(2+4)の出力が成功したかどうかの5倍を戻すことを意味し、
print(2+4) * 5;
は、同じ 5*io成功の値 を戻し、それをトスします。
*x[i]
のように記述すると、括弧は*より緊密に結合します。つまり下記を意味します。
*(x[i])
しかし、Perlでは全く違います! ${}、@{}、%{}、および &{} 表記法は
(完璧を期すには同じく *{} が要るとは思いますが)実際には演算子ではありません。
もしそうなら、*()のように記述する事ができるはずですが、実際にはできません。
その優先順位が簡単に理解できる演算子の代わりに、それらはyaccの文法の架空の代用品(instead figment)なのです。これは:
$$x[$i]
が実際には
{$$x}[$i]
であることを意味しており、(ということは実際のところ)
${$x}[$i]
ということで、
${$x[$i]}
ということではありません。違いが解りますか? よく解らない場合、
血みどろの詳細については
perlref(1)を参照してください。
4.3) 動的と静的(レキシカル)スコープ(有効範囲)の差は
何ですか?
my() と local() の差は何ですか?
スコーピングは変数の可視性に関連します。
動的変数はlocal() 経由で生成され、グローバル変数用のローカル値となりますが、
一方my()経由で生成されたレキシカル変数はCのauto程度かなというあなたの期待を
上回るものです。( 4.4) ディープおよびシャローバインディングの
違いは何ですか?参照)一般的には、レキシカル変数はアクセスが早く、理解も
しやすいので、使えるところではなるべくこちらを使用するよう推奨します。
"use strict vars"プラグマは、全ての変数がレキシカルである、あるいは
パッケージ名によってすべて分類されることを強制します。
我々はあなたが"use strict;" 及び -w フラグを使ってコードを開発することを
強く推奨します。(しかしながら、まだフォーマット(formats)を使う際には
動的変数を使用せざるを得ません。)
下記はその違いの例です。
#!/usr/local/bin/perl
$myvar = 10;
$localvar = 10;
print "Before the sub call - my: $myvar, local: $localvar\n";
&sub1();
print "After the sub call - my: $myvar, local: $localvar\n";
exit(0);
sub sub1 {
my $myvar;
local $localvar;
$myvar = 5; # このブロックの中でのみ有効
$localvar = 20; # 子供(サブルーチン等)からもアクセス可能
print "Inside first sub call - my: $myvar, local: $localvar\n";
&sub2();
}
sub sub2 {
print "Inside second sub - my: $myvar, local: $localvar\n";
}
my()で宣言した変数は、それを命名したブロックのスコープ(範囲)の中でのみ
見えるのです。そのブロックの外側からは見えません。そこからcallしたルーチンや
ブロックの中からでも見えません。一方local()での変数ははそれが宣言された
ブロックからcallされたルーチンからでも見えるのです。
どちらもブロックの終わり(最後の閉じるカーリブレース[訳注:}のこと])の後では
全く見ることはできません。
4.4) ディープおよびシャローバインディング(shallow binding)の
違いは何ですか?
{
my $x = time;
$coderef = sub { $x };
}
&$coderef()をcallしたとき、これは呼び出されたその時にたまたま起きていた
動的な$xがあったらそれを捕まえます。しかしながら、次のように別の振る舞いを
させることができます。
When you call &$coderef(), it will get whatever dynamic $x happens
to be around when invoked. However, you can get the other behaviour
this way:
{
my $x = time;
$coderef = eval "sub { \$x }";
}
さて、これでサブルーチンが生成された時間にセットされるレキシカル変数$xに
アクセスできようになりました。上記2つ振る舞いのの違いは特徴ではなく
バグと考えられます。ですから、将来的には無くなってしまうおそれがありますので
特にシャローバインディングには依存しないようにすべきでしょう。注意して下さい。
perlref(1)参照。
Perl will always give deep binding to functions, so you don't need the
eval hack anymore. Furthermore, functions and even formats
lexically declared nested within another lexical scope have access to
that scope.
require 5.001;
sub mkcounter {
my $start = shift;
return sub {
return ++$start;
}
}
$f1 = mkcounter(10);
$f2 = mkcounter(20);
print &$f1(), &$f2();
11 21
print &$f1(), &$f2(), &$f1();
3.14) 「クロージャ」って何ですか?
参照。
12 22 13
4.5) 固定長レコードファイルを操作するにはどうすればいいですか?
# サンプル入力行:
# 15158 p5 T 0:00 perl /mnt/tchrist/scripts/now-what
$ps_t = 'A6 A4 A7 A5 A*';
open(PS, "ps|");
$_ = <PS> print;
while (<PS>) {
($pid, $tt, $stat, $time, $command) = unpack($ps_t, $_);
for $var ('pid', 'tt', 'stat', 'time', 'command' ) {
print "$var: <", eval "\$$var", ">\n";
}
print 'line=', pack($ps_t, $pid, $tt, $stat, $time, $command), "\n";
}
4.6) サブルーチンに対してローカルなファイルハンドルを
作るにはどうすればいいですか?
sub cat_include {
local($name) = @_;
local(*FILE);
local($_);
warn "<INCLUDING $name>\n";
if (!open (FILE, $name)) {
warn "can't open $name: $!\n";
return;
}
while (
4.7) Perlからalarm() または usleep()をcallするには
どうしたらいいですか?
# alarm; send me a SIGALRM in this many seconds (fractions ok)
# tom christiansen <tchrist@convex.com>
sub alarm {
require 'syscall.ph';
require 'sys/time.ph';
local($ticks) = @_;
local($in_timer,$out_timer);
local($isecs, $iusecs, $secs, $usecs);
local($itimer_t) = 'L4'; # 本来は &itimer'typedef()
$secs = int($ticks);
$usecs = ($ticks - $secs) * 1e6;
$out_timer = pack($itimer_t,0,0,0,0);
$in_timer = pack($itimer_t,0,0,$secs,$usecs);
syscall(&SYS_setitimer, &ITIMER_REAL, $in_timer, $out_timer)
&& die "alarm: setitimer syscall failed: $!";
($isecs, $iusecs, $secs, $usecs) = unpack($itimer_t,$out_timer);
return $secs + ($usecs/1e6);
}
4.8) Perlでは atexit() や setjmp()、longjmp() をどうやっておこなうのですか?
(例外処理)
$SIG{ALRM} = TIMEOUT;
sub TIMEOUT { die "restart input\n" }
do { eval { &realcode } } while $@ =~ /^restart input/;
sub realcode {
alarm 15;
$ans = <STDIN>
alarm 0;
}
下記はTomのatexit()処理を行うサンプルです。
sub atexit { push(@_exit_subs, @_) }
sub _cleanup { unlink $tmp }
&atexit('_cleanup');
eval <<'End_Of_Eval'; $here = __LINE__;
# あなたが必要とするコードをここに
End_Of_Eval
$oops = $@; # エラーメッセージをセーブ
# ここで中身をcall
for (@_exit_subs) { &$_() }
$oops && ($oops =~ s/\(eval\) line (\d+)/$0 .
" line " . ($1+$here)/e, die $oops);
これで&atexit関数を経由してあなた自身のルーチンを登録できるはずです。
また、ヒアドキュメントにあなたの全コードを埋め込むよりも、Larryの
&realcode法を利用したいと考えているかもしれません。
exitよりもdie経由で確実にleaveするようにしてください。
あるいは代わりにあなた自身の&exitルーチンを書き、それをcallしてください。
一般には、この理由で、ネストされたルーチンはexitよりもdie経由でexitする
ほうがよいのです。
4.9) perlではどうやってシグナルを捕捉(catch)するのですか?
$SIG{'INT'} = 'CLEANUP';
sub CLEANUP {
print "\n\nCaught Interrupt (^C), Aborting\n";
exit(1);
}
DEFAULTと IGNOREと呼ばれるシグナル用に2つの特別な"ルーチン"があります。
DEFAULTは現在の割当てを消去し、シグナルのデフォルト値をrestoreします。
IGNOREはignoreされるシグナルを引き起こします。
一般に、標準的なプログラミングの特徴でそれらの機能をエミュレートできるので
それらを覚えておく必要はありません。
DEFAULTは配列からシグナルを削除することでエミュレートできますし、
IGNOREはあらゆる宣言していない(undeclared)サブルーチンによって
エミュレートできます
#!/usr/bin/perl -w
require 5.001;
$SIG{__WARN__} = sub {
if ($_[0] =~ /uninit/) {
die $@;
} else {
warn $@;
}
};
4.10) どうしてPerlは私の8進数データを8進数として
解釈しないのですか?
{
print "What mode would you like? ";
$mode = <STDIN>
$mode = oct($mode);
unless ($mode) {
print "You can't really want mode 0!\n";
redo;
}
chmod $mode, $file;
}
8進数変換無しでは、要求した755のモードは01363に変わり、--wxrw--wtという
奇怪なファイル権限を産み出してしまいます。
$val = oct($val) if $val =~ /^0/;
4.11) 2つの日付の文字列を比較するにはどうしたら
いいでしょうか?
sub getdate {
local($_) = shift;
s/-(\d{4})$/+$1/ || s/\+(\d{4})$/-$1/;
# getdate がタイムゾーンサインを反転してしまう!
$_ = `/usr/local/lib/news/newsbin/getdate '$_'`;
chop;
$_;
}
または、GetDate拡張モジュールを手に入れることもできます。
これは、実際にはperlとリンクしたCコードでできています。
あちこちの素晴らしいPerl拡張モジュールでも逃していた実装法で、
だいたい50倍は早いです。
もしどこにも見つけられなかった時のために、ftp用にperl.comにコピーを
用意しておきます。というのは私(Tom)がこれを移植したからです。
あるいは、次のようなものを利用することを考慮してもよいでしょう。:
date.pl - sysv +FORMAT方法でお望みの日付をprint
date.shar - 日付を操作及び計算するルーチン
ftp-chat2.shar - ftpgetの改訂版。ライブラリとデモプログラムを含む。
getdate.shar - 与えられた日付のepoch(紀元?)からの秒数を戻す。
ptime.shar - sysv +FORMAT方法でお望みの日付をprint
おそらく'getdate.shar'が欲しいでしょうね。これらや他のファイルは
ftp.cis.ufl.eduの/pub/perl/scriptsディレクトリからftp可能です。
timeとヨーロッパのミラーサイトの詳細は/pub/perlディレクトリにある
READMEを参照して下さい。
4.12) ジュリアン日を見つかるにはどうしたらいいですか?
#!/usr/local/bin/perl
@theJulianDate = ( 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 );
#************************************************************************
#**** 閏年の閏日の後にいる場合は1を戻す *****
#************************************************************************
sub leapDay
{
my($year,$month,$day) = @_;
if (year % 4) {
return(0);
}
if (!(year % 100)) { # 原則として100で割り切れる年は
# 閏年ではない。
if (year % 400) { # 但し400で割り切れる年は閏年。
return(0);
}
}
if (month < 2) {
return(0);
} elsif ((month == 2) && (day < 29)) {
return(0);
} else {
return(1);
}
}
#************************************************************************
#**** 求めるジュリアン日の日付、秒数を渡す。 *****
#**** localtime()が年月日を戻す場合はそれを戻し、そうでない場合は *****
#**** ジュリアン日を算出する。 *****
#************************************************************************
sub julianDate
{
my($dateInSeconds) = @_;
my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday);
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) =
localtime($dateInSeconds);
if (defined($yday)) {
return($yday+1);
} else {
return($theJulianDate[$mon] + $mday + &leapDay($year,$mon,$mday));
}
}
print "Today's julian date is: ",&julianDate(time),"\n";
4.13) perlには round関数がありますか?
ceil()とfloor()についてはどうですか?
sub round {
my($number) = shift;
return int($number + .5);
}
この関数が何をしているのか吟味したら、.5以上の数値はみんな次の位の
整数に切り上げられ、.5未満の数値はみんな現在の整数値のままになる
ことがわかるでしょう。これは丸めと同じ効果があります。
return int($number + .5 * ($number <=> 0));
これは渡された数に基づいて、.5を正あるいは負にします。
#!/usr/local/bin/perl
use POSIX qw(ceil floor);
$num = 42.4; # (Pentium上での)最大の質問への答!
print "Floor returns: ", floor($num), "\n";
print "Ceil returns: ", ceil($num), "\n";
出力は:
Floor returns: 42
Ceil returns: 43
4.14) perlで与えられたタスクを書き上げるための最も早いやり方は
何ですか?
$COUNT = 10_000; $| = 1;
print "method 1: ";
($u, $s) = times;
for ($i = 0; $i < $COUNT; $i++) {
# method 1用のコード
}
Perl5 はBenchmark.pmと呼ばれる新しいモジュールを含んでいます。
今ではベンチマークを使用するコードは以下のように簡易化することができます。:
($nu, $ns) = times;
printf "%8.4fu %8.4fs\n", ($nu - $u), ($ns - $s);
print "method 2: ";
($u, $s) = times;
for ($i = 0; $i < $COUNT; $i++) {
# code for method 2
}
($nu, $ns) = times;
printf "%8.4fu %8.4fs\n", ($nu - $u), ($ns - $s);
use Benchmark;
timethese($count, {
Name1 => '...code for method 1...',
Name2 => '...code for method 2...',
... });
だいたい下記に類したものが出力されるでしょう。
Benchmark: timing 100 iterations of Name1, Name2...
Name1: 2 secs (0.50 usr 0.00 sys = 0.50 cpu)
Name2: 1 secs (0.48 usr 0.00 sys = 0.48 cpu)
例えば、次のようなコードは、ある変数に文字列の最初の文字を代入するという
3つの異なった方法の間での時間差を示します。
use Benchmark;
timethese(100000, {
'regex1' => '$str="ABCD"; $str =~ s/^(.)//; $ch = $1',
'regex2' => '$str="ABCD"; $str =~ s/^.//; $ch = $&',
'substr' => '$str="ABCD"; $ch=substr($str,0,1); substr($str,0,1)="",
});
結果はこのようになるかもしれません。:
Benchmark: timing 100000 iterations of regex1, regex2, substr...
regex1: 11 secs (10.80 usr 0.00 sys = 10.80 cpu)
regex2: 10 secs (10.23 usr 0.00 sys = 10.23 cpu)
substr: 7 secs ( 5.62 usr 0.00 sys = 5.62 cpu)
さらに明細な助言は、ラクダ本の終わりの”その他もろもろ”の章にある
効率の問題の節を参照して下さい。
language, like identifiers with any upper-case letters in them.
Therefore, it's fine to do this:
or
longer need one at the end of a block, but stylistically, you're better
to use them if you don't put the curly brace on the same line:
for ($i = 0; $i < @a; $i++) {
print "i is $i\n" # <-- oops!
}
funny. :-)
------------ ---------------
$foo{line} $foo{"line"}
bar => stuff "bar" => stuff
variables are passed by reference. If you say
&munge($x);
sub munge {
local($x);
local($myvar) = $_[0];
...
}
heavy wizardry: the reference to $x stored in $_[0] was temporarily
occluded by the previous local($x) statement (which, you're recall,
occurs at run-time, not compile-time). The work around is simple,
however: declare your formal parameters first:
local($myvar) = $_[0];
local($x);
...
}
directly after the local()s. In this case, careful use of the package
facility is your only recourse.
of the index variable in a foreach() loop.
print "num begin @num\n";
foreach $m (@num) { &ug }
print "num finish @num\n";
sub ug {
local($m) = 42;
print "m=$m $num[0],$num[1],$num[2],$num[3]\n";
}
Which prints out the mysterious:
m=42 42,1,2,3
m=42 0,42,2,3
m=42 0,1,42,3
m=42 0,1,2,42
m=42 0,1,2,3
num finish 0 1 2 3 4
Inside &ug, you temporarily change $m. Well, that means that you've
also temporarily changed whatever $m is an alias to!! The only
workaround is to be careful with global variables, using packages,
and/or just be aware of this potential in foreach() loops.
problem, it often comanifests with a highly undesirable coredumping
problem. Programs known to be affected by the fatal coredump include
plum and pcops. This bug has been fixed since 4.036. It did not
resurface in 5.001.
there is no corresponding mechanism to automatically do the same thing
for a footer. Not knowing how big a format is going to be until you
evaluate it is one of the major problems.
line left on page ($-) before each write, and printing the footer
yourself if necessary.
and always write()ing to the KID, who then postprocesses its STDIN to
rearrange headers and footers however you like. Not very convenient,
but doable.
creaturism". Larry is always adding one more feature, always getting
Perl to handle one more problem. Hence, it keeps growing. Once you've
worked with perl long enough, you will probably start to do the same
thing. You will then notice this problem as you see your scripts
becoming larger and larger.
Mea culpa, I misunderstood you. ;) While there may be a real memory
leak in the Perl source code or even whichever malloc() you're using,
common causes are incomplete eval()s or local()s in loops.
a bit of memory unusable.
local(@array);
}
work-around is:
for (1..100) {
undef @array;
}
eval() still leaks.
when you've introduced a circularity in a data structure that would
normally go out of scope and be unreachable. For example:
my $x;
$x = \$x;
}
there's still something point to $x (itself, in this case). A
full garbage collection system could solve this, but at the cost
of a great deal of complexity in perl itself and some inevitable
performance problems as well. If you're making a circular data
structure that you want freed eventually, you'll have to break the
self-reference links yourself.
program written in Perl can be found in the script ruptime.pl at the
scripts archive on ftp.cis.ufl.edu. I warn you, however, that it's not
a pretty sight, as it's used nothing from h2ph or c2ph, so everything is
utterly hard-wired.
does the error message "Protocol not supported" mean?
standard socket constants. Since these were constant across all
architectures, they were often hardwired into the perl code. The
"proper" way to deal with this is to make sure that you run h2ph
against sys/socket.h, require that file and use the symbolic names
(SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_RDM, and SOCK_SEQPACKET).
values are different, and require a different socket.ph for each OS.
characters in it throwing off the search. If you don't know whether a
pattern is valid or not, enclose it in an eval to avoid a fatal run-
time error.
new quotemeta character (\Q) within your variable.
be assigned to. Therefore, to change the first character to an S, you
could do this:
substr($var,0,1) = 'S';
$[, you should use this instead:
But this won't work if the string is empty or its first character is a
newline, which "." will never match. So you could use this instead:
substr, as in:
works:
For some things it's convenient to use the /e switch of the substitute
operator:
example.
string?
use the tr/// function like so:
$count = ($string =~ tr/X//);
print "There are $count Xs in the string";
if you are trying to count multiple character substrings within a
larger string, tr/// won't work. What you can do is wrap a while loop
around a pattern match.
$count++ while $string =~ /-\d+/g;
print "There are $count negative numbers in the string";
strictly regular because they do backreferencing (the \1 notation), you
still can't do it. You need to employ auxiliary logic. A simple
approach would involve keeping a bit of state around, something
vaguely like this (although we don't handle patterns on the same line):
if (/pat1/) {
if ($inpat++ > 0) { warn "already saw pat1" }
redo;
}
if (/pat2/) {
if (--$inpat < 0) { warn "never saw pat1" }
redo;
}
}
nested single chars, like ` and ', { and }, or ( and ) can be found
on convex.com in /pub/perl/scripts/pull_quotes.
maximum amount of data that they can, sometimes resulting in incorrect
or strange answers.
while ( m#\((.*)\)#g ) {
print "$1\n";
}
parentheses. The expected output was:
example
clearly not what was intended.
group. If the above example is rewritten as follows, the results are
correct:
character is added to the normal metacharacters to modify their
behaviour, such as "*?", "+?", or even "??". The example would now be
written in the following style:
comments from C code:
file?
good time to talk about doing it in perl4. Since comments can be
embedded in strings, or look like function prototypes, care must be
taken to ignore these cases. Jeffrey Friedl* proposes the following
two programs to strip C comments and C++ comments respectively:
C comments:
#!/usr/bin/perl
$/ = undef;
$_ = <>;
]*|'[^'\\]*(\\[\d\D][^'\\]*)*'[^/"']*|/+[^*/][^/"']*)*)#$2#g;
print;
#!/usr/local/bin/perl
$/ = undef;
$_ = <>;
s#//(.*)|/\*[^*]*\*+([^/*][^*]*\*+)*/|"(\\.|[^"\\])*"|'(\\.|[^'\\])*'|[^/"'
]+# $1 ? "/*$1 */" : $& #ge;
print;
correctly.)
[character]?
fields. I could easily use split(/,/), except that I need to not split
if the comma is inside quotes. For example, my data file has a line
like this:
solution. However, we thankfully have Jeff Friedl* to handle these for
us. He suggests (assuming that your data is contained in the special
variable $_):
push(@fields, defined($1) ? $1:$3) while
m/"([^"\\]*(\\.[^"\\]*)*)"|([^,]+)/g;
context, and that the <FILE> syntax in an array context will read all the
lines in a file. To work around this, use:
local($foo);
$foo = <FILE>
You can use the scalar() operator to cast the expression into a scalar
context:
comp.unix.* for things like this: the answer is essentially the same.
It's very system dependent. Here's one solution that works on BSD
systems:
local($rin, $nfd);
vec($rin, fileno(STDIN), 1) = 1;
return $nfd = select($rin,undef,undef,0);
}
your regular perl archive.
input a single character from the keyboard. Again, this is a system
dependent operation. As with the previous question, you probably want
to get the ReadKey extension. The following code may or may not help
you. It should work on both SysV and BSD flavors of UNIX:
if ($BSD) {
system "stty cbreak /dev/tty 2>&1";
}
else {
system "stty", '-icanon',
system "stty", 'eol', "\001";
}
system "stty -cbreak /dev/tty 2>&1";
}
else {
system "stty", 'icanon';
system "stty", 'eol', '^@'; # ascii null
}
print "\n";
going to be doing a lot of them. This code works to toggle cbreak
and echo modes on a BSD system:
local($on) = $_[0];
local($sgttyb,@ary);
require 'sys/ioctl.ph';
$sgttyb_t = 'C4 S' unless $sgttyb_t; # c2ph: &sgttyb'typedef()
if ($on) {
$ary[4] |= &CBREAK;
$ary[4] &= ~&ECHO;
} else {
$ary[4] &= ~&CBREAK;
$ary[4] |= &ECHO;
}
$sgttyb = pack($sgttyb_t,@ary);
}
getc() function; it's in general way too expensive to call for normal
I/O. Normally, you just use the
or sysread() functions.
the file /pub/perl/info/keypress from convex.com.
&Curses::cbreak() and &Curses::nocbreak() to turn cbreak mode on and
off. You can then use getc() to read each character. This should work
under both BSD and SVR systems. If anyone can confirm or deny
(especially William), please contact the maintainers.
from msdos.c (Perl source file) and Ralf Brown's interrupt list (comes
across the net every so often):
$old_ioctl &= 0xff;
ioctl(STDIN,1,$old_ioctl | 32); # Writes it back, setting bit 5
means you hit a special key. Read another byte (sysread(STDIN,$c,1)),
and that value tells you what combination it was according to this
table:
# --- ----
# 0F SHF TAB
# 10-19 ALT QWERTYUIOP
# 1E-26 ALT ASDFGHJKL
# 2C-32 ALT ZXCVBNM
# 3B-44 F1-F10
# 47-49 HOME,UP,PgUp
# 4B LEFT
# 4D RIGHT
# 4F-53 END,DOWN,PgDn,Ins,Del
# 54-5D SHF F1-F10
# 5E-67 CTR F1-F10
# 68-71 ALT F1-F10
# 73-77 CTR LEFT,RIGHT,END,PgDn,HOME
# 78-83 ALT 1234567890-=
# 84 CTR PgUp
file that worked.
screen?
Therefore, there is no direct way in perl to turn echoing on and off.
However, you can call the command "stty [-]echo". The following will
allow you to accept input without it being echoed to the screen, for
example as a way to accept passwords (error checking deleted for
brevity):
system("stty -echo");
chop($password=
print "\n";
system("stty echo");
&Curses::echo() to turn echoing off and on. Or, there's always the
ReadKey extension.
a string?
blanks and replace it with nothing. For example, if you have the
string " String " you can use this:
strings. For longer strings, and worse-case scenarios, they tend to
break-down and become inefficient.
s/^\s*((.*\S)?)\s*$/$1/;
be noticably slower than the simple ones above. It is suggested that
you use whichever one will fit your situation best, understanding that
the first examples will work in roughly ever situation known even if
slow at times.
local($_) = shift;
1 while s/^(-?\d+)(\d{3})/$1,$2/;
return $_;
}
print "GOT: ", &commify($n), "\n";
Some substitutions need to work this way. See the question on
expanding tabs for another such.
1 while s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
あなたは下記のように書いていたはずです。
while (s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {
# spin, spin, spin, ....
}
ある関数の中に置かれた場合:
sub tab_expand {
local($_) = shift;
1 while s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
return $_;
}
その中にタブがあるかもしれないascii文字列をunpackしようとして働いているときには
これは特に重要です。
さもなければ、バイトカウントで間違ってしまうでしょう。
例えば:
$NG = "/usr/local/lib/news/newsgroups";
open(NG, "< $NG") || die "can't open $NG: $!";
while (
4.36) voidコンテキスト中におけるgrep() あるいは map() の使用は
どこがよくないのですか?
@bignums = grep ($_ > 100, @allnums);
@triplist = map {$_ * 3} @allnums;
しかし下記のようにvoidコンテキストにおいて、それを使う場合:
grep{ $_ *= 3, @nums);
これはその副作用を利用するために使われているのですが、
副作用が謎となることもありえます。
for()ループとして書かれないほうがよい void grep などはありません。
for (@nums) { $_ *= 3 }
同じように、voidコンテキストにおける a ?: は貧弱な様式とみなされます。
fork ? wait : exec $prog;
それを下記のように書くことが出来る時はです。:
if (fork) {
wait;
} else {
exec $prog;
die "can't exec $prog: $!";
}
もちろん表現における ?: の使用はそれなりに役に立ちますし、
ただ素晴らしいことです。
(但しそれらをネストしないように心がけること。)
1. 正確性(correctness)
2. 保守性(maintainability)
3. 効率性(efficiency)
賢明さ(cleverness)が絵に入っていない点に留意して下さい。
1. 賢明さ
2. 効率性
3. 保守性
4. 正確性
--
Stephen P Potter Pencom Systems Administration AMP Incorporated
spp@peach.epix.net spp@psa.pencom.com steve.potter@amp.com
Home: 717-540-0131 Pager: 1-800-759-8888, 547-9561 Work: 717-986-5401
Systems Administation: It's a Kind of Magic
ご意見、ご要望は、
電子メールまたは
投稿にお願い致します。