名前¶
perlopentut - simple recipes for opening files and pipes in Perl
perlopentut - Perl でファイルを開いたりパイプを使ったりするための簡単なレシピ
説明¶
Whenever you do I/O on a file in Perl, you do so through what in Perl is called a filehandle. A filehandle is an internal name for an external file. It is the job of the open
function to make the association between the internal name and the external name, and it is the job of the close
function to break that association.
Perl でファイルに対して入出力をするとき、Perl では ファイルハンドル と 呼ばれるものを通して行います。 ファイルハンドルは外部ファイルに対する内部名です。 open
関数の仕事は内部名と外部名を関連づけることで、close
関数は 関連づけを壊すことです。
For your convenience, Perl sets up a few special filehandles that are already open when you run. These include STDIN
, STDOUT
, STDERR
, and ARGV
. Since those are pre-opened, you can use them right away without having to go to the trouble of opening them yourself:
便利なように、Perl は実行開始時に既に開いているいくつかの特別な ファイルハンドルを設定します。 それは STDIN
, STDOUT
, STDERR
, ARGV
です。 これらは既に開いているので、自分でこれらを開くときの問題を受けることなく 正しく使うことができます。
print STDERR "This is a debugging message.\n";
print STDOUT "Please enter something: ";
$response = <STDIN> // die "how come no input?";
print STDOUT "Thank you!\n";
while (<ARGV>) { ... }
As you see from those examples, STDOUT
and STDERR
are output handles, and STDIN
and ARGV
are input handles. They are in all capital letters because they are reserved to Perl, much like the @ARGV
array and the %ENV
hash are. Their external associations were set up by your shell.
これらの例で見られるように、STDOUT
と STDERR
は出力ハンドルで、 STDIN
と ARGV
は入力ハンドルです。 これらは @ARGV
配列や %ENV
ハッシュと同様に Perl によって 予約されているので、全て大文字になっています。 これらの外部関連づけはシェルによって行われます。
You will need to open every other filehandle on your own. Although there are many variants, the most common way to call Perl's open() function is with three arguments and one return value:
その他のファイルハンドルは自分で開く必要があります。 多くのバリエーションはありますが、Perl の open() 関数を開く最も一般的な方法は 3 引数と一つの返り値のものです:
OK = open(HANDLE, MODE, PATHNAME)
OK = open(HANDLE, MODE, PATHNAME)
Where:
ここで:
- OK
-
will be some defined value if the open succeeds, but
undef
if it fails;これは、開くのに成功すれば何らかの定義された値、失敗すれば
undef
です; - HANDLE
-
should be an undefined scalar variable to be filled in by the
open
function if it succeeds;これは、成功すれば
open
関数によって埋められる未定義のスカラ変数です; - MODE
-
is the access mode and the encoding format to open the file with;
これはファイルを開くときのアクセスモードとエンコーディング型式です;
- PATHNAME
-
is the external name of the file you want opened.
これは開きたいファイルの外部名です。
Most of the complexity of the open
function lies in the many possible values that the MODE parameter can take on.
open
関数の複雑さの大部分は、MODE 引数が多くの値を 取ることのできることにあります。
One last thing before we show you how to open files: opening files does not (usually) automatically lock them in Perl. See perlfaq5 for how to lock.
ファイルの開き方を説明する前に最後に一言: Perl ではファイルを開いても (普通は)自動的にロックすることはしません。 ロックの方法については perlfaq5 を参照してください。
テキストファイルを開く¶
読み込み用にテキストファイルを開く¶
If you want to read from a text file, first open it in read-only mode like this:
テキストファイルを読み込みたい場合、まず次のように読み込み専用モードで 開きます:
my $filename = "/some/path/to/a/textfile/goes/here";
my $encoding = ":encoding(UTF-8)";
my $handle = undef; # this will be filled in on success
open($handle, "< $encoding", $filename)
|| die "$0: can't open $filename for reading: $!";
As with the shell, in Perl the "<"
is used to open the file in read-only mode. If it succeeds, Perl allocates a brand new filehandle for you and fills in your previously undefined $handle
argument with a reference to that handle.
シェルと同様に、Perl でもファイルを読み込み専用モードで開くために "<"
が使われます。 これに成功すると、Perl は新しいファイルハンドルを割り当て、未定義だった $handle
引数にそのハンドルへのリファレンスを設定します。
Now you may use functions like readline
, read
, getc
, and sysread
on that handle. Probably the most common input function is the one that looks like an operator:
これでこのハンドルに対して readline
, read
, getc
, sysread
のような関数が使えます。 おそらく最も一般的な入力関数は演算子のように見えるものでしょう:
$line = readline($handle);
$line = <$handle>; # same thing
Because the readline
function returns undef
at end of file or upon error, you will sometimes see it used this way:
readline
関数はファイル終端やエラーのときに undef
を返すので、 時々次のように使われているのを見るでしょう:
$line = <$handle>;
if (defined $line) {
# do something with $line
}
else {
# $line is not valid, so skip it
}
You can also just quickly die
on an undefined value this way:
また、次のようにして単に未定義値に対してすばやく die
することもできます:
$line = <$handle> // die "no input found";
However, if hitting EOF is an expected and normal event, you do not want to exit simply because you have run out of input. Instead, you probably just want to exit an input loop. You can then test to see if an actual error has caused the loop to terminate, and act accordingly:
しかし、EOF に到達するのが想定されていて通常の出来事の場合は、 入力がなくなっただけで終了したくありません。 そうではなく、単に入力ループを終了したいでしょう。 実際のエラーがループを終了させたのかをテストして、適切に行動できます:
while (<$handle>) {
# do something with data in $_
}
if ($!) {
die "unexpected error while reading from $filename: $!";
}
A Note on Encodings: Having to specify the text encoding every time might seem a bit of a bother. To set up a default encoding for open
so that you don't have to supply it each time, you can use the open
pragma:
エンコーディングに関する注意: テキストエンコーディングを毎回指定する 必要があるのは少し面倒に感じるかもしれません。 毎回設定する必要がないように open
のためのデフォルトエンコーディングを 設定するために、open
プラグマを使えます:
use open qw< :encoding(UTF-8) >;
Once you've done that, you can safely omit the encoding part of the open mode:
一度これを行えば、open モードからエンコーディングの部分を安全に省略できます:
open($handle, "<", $filename)
|| die "$0: can't open $filename for reading: $!";
But never use the bare "<"
without having set up a default encoding first. Otherwise, Perl cannot know which of the many, many, many possible flavors of text file you have, and Perl will have no idea how to correctly map the data in your file into actual characters it can work with. Other common encoding formats including "ASCII"
, "ISO-8859-1"
, "ISO-8859-15"
, "Windows-1252"
, "MacRoman"
, and even "UTF-16LE"
. See perlunitut for more about encodings.
しかし、先にデフォルトのエンコーディングを設定することなく裸の "<"
を使うことは決してしないでください。 さもなければ、Perl はとてもとてもとてもたくさんあるテキストファイルの 種類のうちどれかを知ることができず、Perl はあなたのファイルのデータを 動作させるための実際の文字にマッピングすることができません。 その他のよくあるエンコーディング形式には "ASCII"
, "ISO-8859-1"
, "ISO-8859-15"
, "Windows-1252"
, "MacRoman"
および、 "UTF-16LE"
すらもあります。 エンコーディングに関するさらなる情報については perlunitut を 参照してください。
書き込み用にテキストファイルを開く¶
When you want to write to a file, you first have to decide what to do about any existing contents of that file. You have two basic choices here: to preserve or to clobber.
ファイルに書き込みたい場合、そのファイルの既存の内容をどうするかを まず決定する必要があります。 二つの基本的な選択肢があります: 保存するか上書きするかです。
If you want to preserve any existing contents, then you want to open the file in append mode. As in the shell, in Perl you use ">>"
to open an existing file in append mode. ">>"
creates the file if it does not already exist.
既存の内容を保存したい場合、ファイルを追記モードで開きます。 シェルと同様に、 Perl でも既存のファイルを追記モードで開くために ">>"
が使われます。 ファイルがない場合、">>"
はファイルを作ります。
my $handle = undef;
my $filename = "/some/path/to/a/textfile/goes/here";
my $encoding = ":encoding(UTF-8)";
open($handle, ">> $encoding", $filename)
|| die "$0: can't open $filename for appending: $!";
Now you can write to that filehandle using any of print
, printf
, say
, write
, or syswrite
.
これでこのハンドルに対して print
, printf
, say
, write
, syswrite
を使って書き込めます。
As noted above, if the file does not already exist, then the append-mode open will create it for you. But if the file does already exist, its contents are safe from harm because you will be adding your new text past the end of the old text.
前述したように、ファイルが既に存在していない場合、追記モードで開くと ファイルを作ります。 しかしファイルが既に存在している場合、その内容は保護されます; 新しいテキストは 既存のテキストの末尾に追加されるからです。
On the other hand, sometimes you want to clobber whatever might already be there. To empty out a file before you start writing to it, you can open it in write-only mode:
一方、時々、既に何かがあっても上書きしたいときもあります。 書き込みを始める前にファイルを消すために、書き込み専用モードで 開くことができます:
my $handle = undef;
my $filename = "/some/path/to/a/textfile/goes/here";
my $encoding = ":encoding(UTF-8)";
open($handle, "> $encoding", $filename)
|| die "$0: can't open $filename in write-open mode: $!";
Here again Perl works just like the shell in that the ">"
clobbers an existing file.
ここで再び Perl はシェルと同様に動作し、">"
は既存のファイルを 上書きします。
As with the append mode, when you open a file in write-only mode, you can now write to that filehandle using any of print
, printf
, say
, write
, or syswrite
.
追記モードと同様に、ファイルを書き込みモードで開くと、 print
, printf
, say
, write
, syswrite
を使って ファイルハンドルに書き込めるようになります。
What about read-write mode? You should probably pretend it doesn't exist, because opening text files in read-write mode is unlikely to do what you would like. See perlfaq5 for details.
読み書きモードについては? おそらくそれは存在しないというふりをした方がよいでしょう; なぜならテキストファイルを読み書きモードで開いても おそらくあなたが望んでいることをしないからです。 詳しくは perlfaq5 を参照してください。
バイナリファイルを開く¶
If the file to be opened contains binary data instead of text characters, then the MODE
argument to open
is a little different. Instead of specifying the encoding, you tell Perl that your data are in raw bytes.
開こうとしているファイルがテキスト文字ではなくバイナリデータが含まれている 場合、open
の MODE
引数は少し異なるものになります。 エンコーディングを指定する代わりに、データが生のバイト列であることを Perl に知らせます。
my $filename = "/some/path/to/a/binary/file/goes/here";
my $encoding = ":raw :bytes"
my $handle = undef; # this will be filled in on success
And then open as before, choosing "<"
, ">>"
, or ">"
as needed:
それから前述の通り、必要に応じて "<"
, ">>"
, ">"
を選びます:
open($handle, "< $encoding", $filename)
|| die "$0: can't open $filename for reading: $!";
open($handle, ">> $encoding", $filename)
|| die "$0: can't open $filename for appending: $!";
open($handle, "> $encoding", $filename)
|| die "$0: can't open $filename in write-open mode: $!";
Alternately, you can change to binary mode on an existing handle this way:
あるいは、次のようにして既に存在しているハンドルをバイナリモードに 変えることが出来ます:
binmode($handle) || die "cannot binmode handle";
This is especially handy for the handles that Perl has already opened for you.
これは、Perl が既に開いているハンドルに対して特に有用です。
binmode(STDIN) || die "cannot binmode STDIN";
binmode(STDOUT) || die "cannot binmode STDOUT";
You can also pass binmode
an explicit encoding to change it on the fly. This isn't exactly "binary" mode, but we still use binmode
to do it:
また、その場で変更するために binmode
に明示的にエンコーディングを 渡すこともできます。 これは正確には「バイナリ」モードではありませんが、それでも これをするために binmode
を使います:
binmode(STDIN, ":encoding(MacRoman)") || die "cannot binmode STDIN";
binmode(STDOUT, ":encoding(UTF-8)") || die "cannot binmode STDOUT";
Once you have your binary file properly opened in the right mode, you can use all the same Perl I/O functions as you used on text files. However, you may wish to use the fixed-size read
instead of the variable-sized readline
for your input.
一旦バイナリファイルを正しいモードで適切に開くと、テキストファイルで 使ったものと全て同じ Perl I/O 関数を使えます。 しかし、入力に対して可変長の readline
ではなく固定長の read
を使った方が良いでしょう。
Here's an example of how to copy a binary file:
次のものはバイナリファイルをコピーする例です:
my $BUFSIZ = 64 * (2 ** 10);
my $name_in = "/some/input/file";
my $name_out = "/some/output/flie";
my($in_fh, $out_fh, $buffer);
open($in_fh, "<", $name_in)
|| die "$0: cannot open $name_in for reading: $!";
open($out_fh, ">", $name_out)
|| die "$0: cannot open $name_out for writing: $!";
for my $fh ($in_fh, $out_fh) {
binmode($fh) || die "binmode failed";
}
while (read($in_fh, $buffer, $BUFSIZ)) {
unless (print $out_fh $buffer) {
die "couldn't write to $name_out: $!";
}
}
close($in_fh) || die "couldn't close $name_in: $!";
close($out_fh) || die "couldn't close $name_out: $!";
パイプを開く¶
Perl also lets you open a filehandle into an external program or shell command rather than into a file. You can do this in order to pass data from your Perl program to an external command for further processing, or to receive data from another program for your own Perl program to process.
Perl はまた、ファイルではなく外部プログラムやシェルコマンドへの ファイルハンドルも開きます。 これを、更なる処理のために Perl プログラムから外部コマンドへ渡すため、 または処理する Perl プログラムのために他のプログラムからデータを 受け取るために行えます。
Filehandles into commands are also known as pipes, since they work on similar inter-process communication principles as Unix pipelines. Such a filehandle has an active program instead of a static file on its external end, but in every other sense it works just like a more typical file-based filehandle, with all the techniques discussed earlier in this article just as applicable.
コマンドへのファイルハンドルは、パイプ としても知られます; Unix パイプラインという似たようなプロセス間通信原則に基づいて 動作するからです。 そのようなファイルハンドルは、外側が静的なファイルではなく 動作中のプログラムですが、それ以外の点については より典型的なファイルベースのファイルハンドルとちょうど同じように 動作し、この文書で既に議論した全てのテクニックが利用可能です。
As such, you open a pipe using the same open
call that you use for opening files, setting the second (MODE
) argument to special characters that indicate either an input or an output pipe. Use "-|"
for a filehandle that will let your Perl program read data from an external program, and "|-"
for a filehandle that will send data to that program instead.
2 番目の (MODE
) 引数にパイプの入力または出力を示す特殊な文字を 設定することで、ファイルを開くのに使うのと同じ open
で パイプを開きます。 Perl プログラムが外部プログラムからデータを読み込むファイルハンドルには "-|"
を使います; プログラムにデータを送るファイルハンドルには "|-"
を使います。
読み込み用にパイプを開く¶
Let's say you'd like your Perl program to process data stored in a nearby directory called unsorted
, which contains a number of textfiles. You'd also like your program to sort all the contents from these files into a single, alphabetically sorted list of unique lines before it starts processing them.
たくさんのテキストファイルが含まれている、unsorted
と呼ばれる 近くのディレクトリに保管されているデータを処理する Perl プログラムが欲しいとしましょう。 また、処理を開始する前に、複数のファイルを単一の、ユニークな行を アルファベット順にソートしたいとします。
You could do this through opening an ordinary filehandle into each of those files, gradually building up an in-memory array of all the file contents you load this way, and finally sorting and filtering that array when you've run out of files to load. Or, you could offload all that merging and sorting into your operating system's own sort
command by opening a pipe directly into its output, and get to work that much faster.
それぞれのファイルに対して通常のファイルハンドルを開き、 このようにして読み込んだ全てのファイルの内容を徐々にメモリ内の配列に 構築し、読み込むファイルがなくなったら最後にソートとフィルタリングをする、 という形でこれを行うことも出来ます。 あるいは、結合とソートをオペレーティング自身の sort
コマンドに 任せて、その出力を直接パイプで開くことで、遙かに速く作業することも出来ます。
Here's how that might look:
以下は、これがどのように見えるかです:
open(my $sort_fh, '-|', 'sort -u unsorted/*.txt')
or die "Couldn't open a pipe into sort: $!";
# And right away, we can start reading sorted lines:
while (my $line = <$sort_fh>) {
#
# ... Do something interesting with each $line here ...
#
}
The second argument to open
, "-|"
, makes it a read-pipe into a separate program, rather than an ordinary filehandle into a file.
open
の 2 番目の引数である "-|"
は、ファイルへの通常の ファイルハンドルではなく、別個のプログラムへの読み込みパイプにします。
Note that the third argument to open
is a string containing the program name (sort
) plus all its arguments: in this case, -u
to specify unqiue sort, and then a fileglob specifying the files to sort. The resulting filehandle $sort_fh
works just like a read-only ("<"
) filehandle, and your program can subsequently read data from it as if it were opened onto an ordinary, single file.
open
の 3 番目の引数は、 プログラム名 (sort
) とその全ての引数を含んだ文字列です: この場合、-u
はユニークソートを指定し、それからファイルグロブは ソートするファイルを指定することに注意してください。 結果のファイルハンドル $sort_fh
は ちょうど読み込み専用 ("<"
) ファイルハンドルのように動作し、 プログラムは、通常の単一のファイルが開かれたかのように、 引き続いてそこからデータを読み込むことができます。
書き込み用にパイプを開く¶
Continuing the previous example, let's say that your program has completed its processing, and the results sit in an array called @processed
. You want to print these lines to a file called numbered.txt
with a neatly formatted column of line-numbers.
前回の例の続きとして、プログラムの処理を完成させて、 結果は @processed
と呼ばれる配列に入っているとしましょう。 これらの行を numbered.txt
というファイル名に、 いい感じに整形された行番号の列と共に出力したいとします。
Certainly you could write your own code to do this ? or, once again, you could kick that work over to another program. In this case, cat
, running with its own -n
option to activate line numbering, should do the trick:
確かにこれをするコードを自分で書くこともできます - あるいは、再び、 この作業を他のプログラムに送ることもできます。 この場合、cat
を、行番号付けを有効にする -n
オプション込みで 実行するには、次の技を使います:
open(my $cat_fh, '|-', 'cat -n > numbered.txt')
or die "Couldn't open a pipe into cat: $!";
for my $line (@processed) {
print $cat_fh $line;
}
Here, we use a second open
argument of "|-"
, signifying that the filehandle assigned to $cat_fh
should be a write-pipe. We can then use it just as we would a write-only ordinary filehandle, including the basic function of print
-ing data to it.
ここで、open
の 2 番目の引数に "|-"
を使います; これにより、$cat_fh
に代入されるファイルハンドルが書き込み パイプであることを示します。 それから、データを print
する基本的な関数を含めて、 書き込み専用の普通のファイルハンドルを使うのと同じようにこれを使えます。
Note that the third argument, specifying the command that we wish to pipe to, sets up cat
to redirect its output via that ">"
symbol into the file numbered.txt
. This can start to look a little tricky, because that same symbol would have meant something entirely different had it showed it in the second argument to open
! But here in the third argument, it's simply part of the shell command that Perl will open the pipe into, and Perl itself doesn't invest any special meaning to it.
パイプしたいコマンドを指定する 3 番目の引数は、 cat
の出力を ">"
記号を使ってファイル numbered.txt
に リダイレクトするように指定していることに注意してください。 これは最初は少しおかしく見えるかもしれません; この同じ記号は、open
の 2 番目の引数では全く違うものを意味するからです! しかし、ここ 3 番目の引数では、これは単に Perl がパイプを開く シェルコマンドの一部であり、Perl 自身はこれに何の特別な意味も与えません。
コマンドをリストとして表現する¶
For opening pipes, Perl offers the option to call open
with a list comprising the desired command and all its own arguments as separate elements, rather than combining them into a single string as in the examples above. For instance, we could have phrased the open
call in the first example like this:
パイプを開くために、Perl は、目的のコマンドとそれ自身の引数を、 前述の例のように単一の文字列として結合するのではなく、 別個の要素として構成されたリストで open
を呼び出すという 選択肢を提供しています。 例えば、最初の例の open
呼び出しは次のように書けます:
open(my $sort_fh, '-|', 'sort', '-u', glob('unsorted/*.txt'))
or die "Couldn't open a pipe into sort: $!";
When you call open
this way, Perl invokes the given command directly, bypassing the shell. As such, the shell won't try to interpret any special characters within the command's argument list, which might overwise have unwanted effects. This can make for safer, less error-prone open
calls, useful in cases such as passing in variables as arguments, or even just referring to filenames with spaces in them.
この方法で open
を呼び出す場合、 Perl はシェルをバイパスして指定されたコマンドを直接起動します。 シェルはコマンド路の引数リストの中の特殊文字を解釈しようとはしません; さもなければ望まない効果を生むことがあります。 これはより安全で、open
呼び出しの誤りを減らし、 引数として変数の内容を渡すような場合に有用で、 単に空白を含むファイルを参照する場合にも安全です。
However, when you do want to pass a meaningful metacharacter to the shell, such with the "*"
inside that final unsorted/*.txt
argument here, you can't use this alternate syntax. In this case, we have worked around it via Perl's handy glob
built-in function, which evaluates its argument into a list of filenames ? and we can safely pass that resulting list right into open
, as shown above.
しかし、シェルに意味のあるメタ文字を 渡したい、 例えば最終的な unsorted/*.txt
の中の "*"
のような場合、 この代替文法は使えません。 この場合、引数をファイル名として評価する Perl の便利な glob
組み込み関数で 回避します; そして前述したように、結果のリストを open
に安全に 渡せます。
Note also that representing piped-command arguments in list form like this doesn't work on every platform. It will work on any Unix-based OS that provides a real fork
function (e.g. macOS or Linux), as well as on Windows when running Perl 5.22 or later.
また、このようなリスト形式でのパイプコマンド引数表現は、全ての プラットフォームで動作するわけではないことに注意してください。 真の fork
関数を提供する Unix ベースの OS (例えば macOS や Linux)、 および Perl 5.22 以降の Windows では動作します。
SEE ALSO¶
The full documentation for open
provides a thorough reference to this function, beyond the best-practice basics covered here.
open
の完全な文書は、 ここでカバーしているベストプラクティスベースのものを超えて、 この関数の完全なリファレンスを提供します。
AUTHOR and COPYRIGHT¶
Copyright 2013 Tom Christiansen; now maintained by Perl5 Porters
This documentation is free; you can redistribute it and/or modify it under the same terms as Perl itself.