- 名前
- 説明
- データ: 数
- データ:日付
- データ: 文字列
- 入力を検査するには?
- 文字列のアンエスケープ (unescape)をするには?
- キャラクタの連続した組を取り除くには?
- 文字列中にある関数呼び出しを展開するには?
- 何かがマッチしている/ネストしているということを検出するには?
- 文字列をひっくり返すには?
- 文字列中にあるタブを展開するには?
- 段落を整形するには?
- 文字列の最初の N 文字にアクセスしたり、それを変更するには?
- 何かの N 番目のものを変更するには?
- ある文字列の中に存在する部分文字列が何個あるのかを数えるには?
- 一行にあるすべての単語をキャピタライズするには?
- (とある文字)の内側にある時を除き、(とある文字)で終端されている文字列を分割するには?
- 文字列の先頭や末尾にある空白を剥ぎ取るには?
- 文字列に空白をパッディングしたり、数値にゼロをパッディングしたりするには?
- 文字列から選択されたカラムを取り出すには?
- 文字列の soundex 値を見つけるには?
- テキスト文字列の中にある変数を展開するには?
- 常にクォーティング "$vars" することの何が悪いの?
- なぜ私の <
- データ: 配列
- リストと配列の差とはなんですか?
- $array[1] と @array[1] との間の違いはなんですか?
- 配列やリストにある重複した要素を削除するには?
- リストや配列の内容にある特定の要素があるかどうかを確かめるには?
- 二つの配列の差(difference)を求めるには? 二つの配列の共通要素(inter section)を求めるには?
- 二つの配列や二つのハッシュが等しいかどうかを検査するには?
- ある条件が真となる最初の配列要素を見つけだすには?
- リンク付きリストを扱うには?
- 循環リストを扱うには?
- 配列をランダムにかき混ぜるには?
- 配列の各要素に対する処理や、変更を行うには?
- ある配列からランダムに要素を選択するには?
- N 要素を持つリストの順列(permute)を求めるには?
- (なにか)で配列をソートするには?
- ビット配列を扱うには?
- なぜ空の配列やハッシュに defined() を使ったときに真が返ってくるのでしょう?
- データ: ハッシュ(連想配列)
- ハッシュ全体を処理するには?
- 二つのハッシュをマージするには?
- ハッシュに対して反復操作を行っているときにキーの追加や削除をすると何が起きますか?
- ハッシュの要素をその値で検索するには?
- ハッシュにどれくらいの要素があるのを知るには?
- ハッシュを(キーではなく値で)ソートするには?
- 私のハッシュを常にソートされた状態にしておくには?
- ハッシュに対する "delete" と "undef"との間の違いは?
- なぜわたしの tie されたハッシュは defined と exists を区別しないのでしょうか?
- each() 操作の途中でリセットしてしまうには?
- 二つのハッシュからユニークなキーを取りだすには?
- DBM ファイルに多次元配列を格納するには?
- わたしのハッシュが格納した順番を覚えておくようにするには?
- なぜあるハッシュの未定義要素をサブルーチンに渡すとそれを作成するのでしょうか?
- C の構造体/C++ のクラスのハッシュ、配列のハッシュ、配列と等価なものを Perl で作成するには?
- ハッシュのキーとしてリファレンスを使うには?
- 複数レベルハッシュにキーがあるかどうかをチェックするには?
- データ:その他
- AUTHOR AND COPYRIGHT
名前¶
perlfaq4 - Data Manipulation
perlfaq4 - データ操作
説明¶
This section of the FAQ answers questions related to manipulating numbers, dates, strings, arrays, hashes, and miscellaneous data issues.
FAQのこのセクションでは、数値、日付、文字列、配列、ハッシュその他の データの取り扱いに関する質問に回答しています。
データ: 数¶
なぜ 19.95 のような数字ではなく、19.9499999999999 のような長い数字が出てきたんでしょうか?¶
For the long explanation, see David Goldberg's "What Every Computer Scientist Should Know About Floating-Point Arithmetic" (http://web.cse.msu.edu/~cse320/Documents/FloatingPoint.pdf).
長い説明としては、David Goldberg の "What Every Computer Scientist Should Know About Floating-Point Arithmetic" (http://web.cse.msu.edu/~cse320/Documents/FloatingPoint.pdf) を 参照してください。
Internally, your computer represents floating-point numbers in binary. Digital (as in powers of two) computers cannot store all numbers exactly. Some real numbers lose precision in the process. This is a problem with how computers store numbers and affects all computer languages, not just Perl.
内部的には、あなたの使っているコンピュータは浮動小数点数を 2 進数を 使って表現しています。 (2 のべき乗のような) デジタルなコンピュータは全ての数値を正確に 保管することはできません。 実数は処理中に精度が落ちることがあります。 これはコンピュータがどのように数値を保管するかの問題で、Perl だけではなく 全てのコンピュータ言語に影響を与えます。
perlnumber shows the gory details of number representations and conversions.
perlnumber には、数値表現と変換に関する不愉快な詳細が記されています。
To limit the number of decimal places in your numbers, you can use the printf
or sprintf
function. See "Floating Point Arithmetic" in perlop for more details.
10 進数の桁数を制限するには、printf
や sprintf
の関数が使えます。 更なる詳細については "Floating Point Arithmetic" in perlop を参照してください。
printf "%.2f", 10/3;
my $number = sprintf "%.2f", 10/3;
なぜ int() は壊れているのでしょう?¶
Your int()
is most probably working just fine. It's the numbers that aren't quite what you think.
int()
はほぼ確実に正しく動作しています。 これは、数値というものがあなたの考えているものと違うからです。
First, see the answer to "Why am I getting long decimals (eg, 19.9499999999999) instead of the numbers I should be getting (eg, 19.95)?".
まず、"Why am I getting long decimals (eg, 19.9499999999999) instead of the numbers I should be getting (eg, 19.95)?" に対する答えを参照してください。
For example, this
例えば、これは:
print int(0.6/0.2-2), "\n";
will in most computers print 0, not 1, because even such simple numbers as 0.6 and 0.2 cannot be presented exactly by floating-point numbers. What you think in the above as 'three' is really more like 2.9999999999999995559.
ほとんどのコンピュータでは 1 ではなく 0 を表示します; 0.6 や 0.2 と言った単純な数値であっても、浮動小数点数で正確に表現できません。 さきほどあなたが "3" と考えたものは、実際には 2.9999999999999995559 と いったものです。
なぜ私の 8 進データは正しく解釈されないのでしょうか?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
You're probably trying to convert a string to a number, which Perl only converts as a decimal number. When Perl converts a string to a number, it ignores leading spaces and zeroes, then assumes the rest of the digits are in base 10:
おそらく文字列を数値に変換しようとしているのでしょうが、Perl は 10 進数しか変換しません。 Perl が文字列を数値に変換するとき、先頭の空白とゼロは無視して、残りの 数字は 10 進数であると仮定します:
my $string = '0644';
print $string + 0; # prints 644
print $string + 44; # prints 688, certainly not octal!
This problem usually involves one of the Perl built-ins that has the same name a Unix command that uses octal numbers as arguments on the command line. In this example, chmod
on the command line knows that its first argument is octal because that's what it does:
この問題は普通コマンドライン引数として 8 進数を使う同じ名前の Unix コマンドがある Perl 組み込み関数に関わります。 この例では、コマンドラインの chmod
は、最初の引数として 8 進数を 求めているので、最初の引数が 8 進数だと分かっています:
%prompt> chmod 644 file
If you want to use the same literal digits (644) in Perl, you have to tell Perl to treat them as octal numbers either by prefixing the digits with a 0
or using oct
:
もし同じリテラルの数字 (644) を Perl で使いたいなら、 先頭に 0
を付けるか oct
を使うことで Perl にこれを 8 進数で 扱うように教える必要があります:
chmod( 0644, $file); # right, has leading zero
chmod( oct(644), $file ); # also correct
The problem comes in when you take your numbers from something that Perl thinks is a string, such as a command line argument in @ARGV
:
この問題は、Perl が文字列として考えているところ、例えば @ARGV
のコマンドライン引数から数字を持ってくる場合に起こります:
chmod( $ARGV[0], $file); # wrong, even if "0644"
chmod( oct($ARGV[0]), $file ); # correct, treat string as octal
You can always check the value you're using by printing it in octal notation to ensure it matches what you think it should be. Print it in octal and decimal format:
使っている値があなたの考えている形と一致しているかを確認するために、 いつでも値を 8 進表記で表示することでチェックできます。 8 進数と 10 進数で表示します:
printf "0%o %d", $number, $number;
Perl には丸め関数がありますか? ceil() と floor() とは何ですか? 三角関数は?¶
Remember that int()
merely truncates toward 0. For rounding to a certain number of digits, sprintf()
or printf()
is usually the easiest route.
int()
は 0 へ向かって丸めを行うことを思い出してください。 特定の桁数で丸めを行うには、sprintf()
や printf()
を使うことが 通常はもっとも簡単なやり方です。
printf("%.3f", 3.1415926535); # prints 3.142
The POSIX
module (part of the standard Perl distribution) implements ceil()
, floor()
, and a number of other mathematical and trigonometric functions.
(標準 Perl 配布キットの一部である)POSIX
モジュールは ceil()
、 floor()
、そしてその他の数学的な関数や三角関数の多くを実装しています。
use POSIX;
$ceil = ceil(3.5); # 4
$floor = floor(3.5); # 3
In 5.000 to 5.003 perls, trigonometry was done in the Math::Complex
module. With 5.004, the Math::Trig
module (part of the standard Perl distribution) implements the trigonometric functions. Internally it uses the Math::Complex
module and some functions can break out from the real axis into the complex plane, for example the inverse sine of 2.
perl の 5.000 から 5.003 では、三角関数は Math::Complex
モジュールの中で 実行されていました。 5.004 では、Math::Trig
モジュール(標準 Perl 配布キットの一部です)が 三角関数を実装しています。 内部的にはこれは Math::Complex
を使っていて、一部の関数は実数値を複素数領域へ 変化させることができます。 2 の inverse sine がその一例です。
Rounding in financial applications can have serious implications, and the rounding method used should be specified precisely. In these cases, it probably pays not to trust whichever system of rounding is being used by Perl, but instead to implement the rounding function you need yourself.
金融に関係するアプリケーションにおいては、丸めはきちんとした実装を 必要とするかもしれません。 そして、丸めの方法は適切に使われるべきものです。 この場合、Perl が使っているシステムによる丸めを信用すべきではなく、 自分自身で丸め関数を実装するようにすべきでしょう。
To see why, notice how you'll still have an issue on half-way-point alternation:
なぜかを見るために、中間点反復に関する問題があるということに注意しましょう:
for ($i = 0; $i < 1.01; $i += 0.05) { printf "%.1f ",$i}
0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7
0.8 0.8 0.9 0.9 1.0 1.0
Don't blame Perl. It's the same as in C. IEEE says we have to do this. Perl numbers whose absolute values are integers under 2**31 (on 32-bit machines) will work pretty much like mathematical integers. Other numbers are not guaranteed.
Perl を責めないでください。 これはCでも同じことなのです。 IEEE ではこのようにすることを述べています。 Perl での数値は絶対値で 2**31(32 ビットマシンの場合)以下の場合の整数値であれば 数学的な整数と同じように振る舞います。 それ以外の数値は恩恵を受けません。
数値表現や基底や基数を変換するには?¶
As always with Perl there is more than one way to do it. Below are a few examples of approaches to making common conversions between number representations. This is intended to be representational rather than exhaustive.
Perl ではいつものことですが、これを行うには複数の方法があります。 以下は、一般的な数値表現の変換を行うための手法のいくつかの例です。 これは完全性よりも説明性を意図しています。
Some of the examples later in perlfaq4 use the Bit::Vector
module from CPAN. The reason you might choose Bit::Vector
over the perl built-in functions is that it works with numbers of ANY size, that it is optimized for speed on some operations, and for at least some programmers the notation might be familiar.
perlfaq4 の後の方での例では CPAN にある Bit::Vector
を使っています。 perl 組み込みの関数よりも Bit::Vector
を選択する理由は、 どんな大きさの数でも動作し、いくつかの操作では速度のために最適化されていて、 少なくともいくらかのプログラマにとっては表記がわかりやすいからです。
- How do I convert hexadecimal into decimal
-
(16 進数を 10 進数に変換するには?)
Using perl's built in conversion of
0x
notation:0x
表記による perl の組み込み変換を使って:$dec = 0xDEADBEEF;
Using the
hex
function:hex
関数を使って:$dec = hex("DEADBEEF");
Using
pack
:pack
を使って:$dec = unpack("N", pack("H8", substr("0" x 8 . "DEADBEEF", -8)));
Using the CPAN module
Bit::Vector
:CPAN の
Bit::Vector
モジュールを使って:use Bit::Vector; $vec = Bit::Vector->new_Hex(32, "DEADBEEF"); $dec = $vec->to_Dec();
- How do I convert from decimal to hexadecimal
-
(10 進数を 16 進数に変換するには?)
Using
sprintf
:sprintf
を使って:$hex = sprintf("%X", 3735928559); # upper case A-F $hex = sprintf("%x", 3735928559); # lower case a-f
Using
unpack
:unpack
を使って:$hex = unpack("H*", pack("N", 3735928559));
Using
Bit::Vector
:Bit::Vector
を使って:use Bit::Vector; $vec = Bit::Vector->new_Dec(32, -559038737); $hex = $vec->to_Hex();
And
Bit::Vector
supports odd bit counts:そして
Bit::Vector
は半端なビット数にも対応しています:use Bit::Vector; $vec = Bit::Vector->new_Dec(33, 3735928559); $vec->Resize(32); # suppress leading 0 if unwanted $hex = $vec->to_Hex();
- How do I convert from octal to decimal
-
(8 進数を 10 進数に変換するには?)
Using Perl's built in conversion of numbers with leading zeros:
先頭に 0 を付けることによる Perl 組み込みの変換を使って:
$dec = 033653337357; # note the leading 0!
Using the
oct
function:oct
function 関数を使って:$dec = oct("33653337357");
Using
Bit::Vector
:Bit::Vector
を使って:use Bit::Vector; $vec = Bit::Vector->new(32); $vec->Chunk_List_Store(3, split(//, reverse "33653337357")); $dec = $vec->to_Dec();
- How do I convert from decimal to octal
-
(10 進数を 8 進数に変換するには?)
Using
sprintf
:sprintf
を使って:$oct = sprintf("%o", 3735928559);
Using
Bit::Vector
:Bit::Vector
を使って:use Bit::Vector; $vec = Bit::Vector->new_Dec(32, -559038737); $oct = reverse join('', $vec->Chunk_List_Read(3));
- How do I convert from binary to decimal
-
(2 進数から 10 進数に変換するには?)
Perl 5.6 lets you write binary numbers directly with the
0b
notation:Perl 5.6 から、
0b
表記を使って直接 2 進数を書くことができます:$number = 0b10110110;
Using
oct
:oct
を使って:my $input = "10110110"; $decimal = oct( "0b$input" );
Using
pack
andord
:pack
とord
を使って:$decimal = ord(pack('B8', '10110110'));
Using
pack
andunpack
for larger strings:より大きな文字列に対しては、
pack
とunpack
を使って:$int = unpack("N", pack("B32", substr("0" x 32 . "11110101011011011111011101111", -32))); $dec = sprintf("%d", $int); # substr() is used to left-pad a 32-character string with zeros.
Using
Bit::Vector
:Bit::Vector
を使って:$vec = Bit::Vector->new_Bin(32, "11011110101011011011111011101111"); $dec = $vec->to_Dec();
- How do I convert from decimal to binary
-
Using
sprintf
(perl 5.6+):sprintf
を使って(perl 5.6 以降):$bin = sprintf("%b", 3735928559);
Using
unpack
:unpack
を使って:$bin = unpack("B*", pack("N", 3735928559));
Using
Bit::Vector
:Bit::Vector
を使って:use Bit::Vector; $vec = Bit::Vector->new_Dec(32, -559038737); $bin = $vec->to_Bin();
The remaining transformations (e.g. hex -> oct, bin -> hex, etc.) are left as an exercise to the inclined reader.
残りの変換 (16 進 -> 8 進、2 進 -> 16 進、など) は読者への宿題として 残しておきます。
なぜ & は私の思った通りに動作しないのでしょうか?¶
The behavior of binary arithmetic operators depends on whether they're used on numbers or strings. The operators treat a string as a series of bits and work with that (the string "3"
is the bit pattern 00110011
). The operators work with the binary form of a number (the number 3
is treated as the bit pattern 00000011
).
バイナリ算術演算子の振る舞いはそれが数値に対して使われているのか 文字列に対して使われているかということに依存しています。 その演算子は文字列をビットの並びとして扱います("3"
という文字列は 00110011
というビットパターンとなります)。 この演算子はバイナリ形式に対して働きます (3
という数値は 00000011
というビットパターンとして扱われます)。
So, saying 11 & 3
performs the "and" operation on numbers (yielding 3
). Saying "11" & "3"
performs the "and" operation on strings (yielding "1"
).
ですから、11 & 3
は数値に対する "and" として働きます(結果は 3
です)。 "11" & "3"
は文字列に対する "and" として働きます(結果は "1"
です)。
Most problems with &
and |
arise because the programmer thinks they have a number but really it's a string or vice versa. To avoid this, stringify the arguments explicitly (using ""
or qq()
) or convert them to numbers explicitly (using 0+$arg
). The rest arise because the programmer says:
ありがちな問題は &
と |
を使ったときに、プログラマは オペランドが数値と考えているのに実際は文字列であるようなときに、 またはその逆の時に起こります。 これを避けるために、(""
や qq()
を使って) 引数を明示的に 文字列化するか、(0+$arg
を使って)明示的に数値に変換してください。 例を挙げましょう:
if ("\020\020" & "\101\101") {
# ...
}
but a string consisting of two null bytes (the result of "\020\020" & "\101\101"
) is not a false value in Perl. You need:
この場合の結果は二つのナルバイトを含む文字列となります ("\020\020"
の結果です)が、これは Perl における偽の値では ありません。 以下のようにする必要があります:
if ( ("\020\020" & "\101\101") !~ /[^\000]/) {
# ...
}
行列の積を計算するには?¶
Use the Math::Matrix
or Math::MatrixReal
modules (available from CPAN) or the PDL
extension (also available from CPAN).
Math::Matrix モジュールか、Math::MatrixReal モジュール(CPAN で入手できます)か PDL エクステンション(これも CPAN で入手できます)を使います。
整数値の並びに対してある操作を実行するには?¶
To call a function on each element in an array, and collect the results, use:
配列の各要素に対して関数を呼び出して、結果を集めるにはこうします:
@results = map { my_func($_) } @array;
For example:
例えば:
@triple = map { 3 * $_ } @single;
To call a function on each element of an array, but ignore the results:
配列の各要素に対して関数を呼び出すけれども、結果を無視するという 場合にはこうします:
foreach $iterator (@array) {
some_func($iterator);
}
To call a function on each integer in a (small) range, you can use:
ある(小さな)範囲にある整数に対して関数を呼び出すには、こうも できます:
@results = map { some_func($_) } (5 .. 25);
but you should be aware that the ..
operator creates a list of all integers in the range. This can take a lot of memory for large ranges. Instead use:
ただし、..
演算子がその範囲にあるすべての整数のリストを生成するということに 注意すべきでしょう。 これによって大きな範囲を使った場合に大量のメモリを消費することになります。 代わりにこうします:
@results = ();
for ($i=5; $i <= 500_005; $i++) {
push(@results, some_func($i));
}
This situation has been fixed in Perl5.005. Use of ..
in a for
loop will iterate over the range, without creating the entire range.
この状況は Perl5.005 で修正されました。 for
ループで ..
を使うことで、 範囲全体を生成することなく特定の範囲の繰り返しを行えます。
for my $i (5 .. 500_005) {
push(@results, some_func($i));
}
will not create a list of 500,000 integers.
このようにしても 500,000 個の整数のリストが生成されたりはしません。
ローマ数字を出力するには?¶
Get the http://www.cpan.org/modules/by-module/Roman module.
http://www.cpan.org/modules/by-module/Roman モジュールを入手しましょう。
なぜ私の乱数はランダムでないの?¶
If you're using a version of Perl before 5.004, you must call srand
once at the start of your program to seed the random number generator.
5.004 より前のバージョンの Perl を使っているなら、srand
を プログラムの開始時点で一度呼び出してやって、乱数生成器の種を セットしてやらなければなりません。
BEGIN { srand() if $] < 5.004 }
5.004 and later automatically call srand
at the beginning. Don't call srand
more than once--you make your numbers less random, rather than more.
5.004 以降のものでは開始時点で自動的に srand
を呼び出します。 二度以上 srand
を呼び出してはいけません。 乱数の質を落としてしまいます。
Computers are good at being predictable and bad at being random (despite appearances caused by bugs in your programs :-). The random article in the "Far More Than You Ever Wanted To Know" collection in http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz, courtesy of Tom Phoenix, talks more about this. John von Neumann said, "Anyone who attempts to generate random numbers by deterministic means is, of course, living in a state of sin."
コンピュータは予測できる物事に関しては役に立ちますが、ランダムな ことに対してはそうではありません(それはあなたのプログラム自身のバグによって 引き起こされることですが:-) http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz の "Far More Than You Ever Wanted To Know" の中の random という記事で Tom Phoenix がこの問題について語ってます。 ジョン・フォン・ノイマン曰く、「決定論的手段によって 乱数を作ろうと試みる全ての人はもちろん罪深きものである。」
If you want numbers that are more random than rand
with srand
provides, you should also check out the Math::TrulyRandom
module from CPAN. It uses the imperfections in your system's timer to generate random numbers, but this takes quite a while. If you want a better pseudorandom generator than comes with your operating system, look at "Numerical Recipes in C" at http://www.nr.com/.
rand
と srand
が提供するものよりもよりランダムな数値が必要なら、 CPAN にある Math::TrulyRandom
モジュールも チェックしてみると良いでしょう。 これはあなたの使っているシステムのタイマーを乱数を生成するのに 使っていて不完全な面もありますが、十分なものです。 あなたの使うオペレーティングシステムで使えるものよりも もっと良質な擬似乱数を必要としているのなら、 http://www.nr.com にある ``Numerical Recipes in C'' を見るとよいでしょう。
X と Y の間の乱数を得るには?¶
To get a random number between two values, you can use the rand()
built-in to get a random number between 0 and 1. From there, you shift that into the range that you want.
二つの値の間の乱数を得るためには、まず 0 と 1 との間の乱数を得るために rand()
組み込み関数を使います。 それから、これを必要な範囲にシフトします。
rand($x)
returns a number such that 0 <= rand($x) < $x
. Thus what you want to have perl figure out is a random number in the range from 0 to the difference between your X and Y.
rand($x)
は 0 <= rand($x) < $x
という値を返します。 従って、perl に作ってほしいものは、0 から、必要な X と Y との差 までの範囲の乱数です。
That is, to get a number between 10 and 15, inclusive, you want a random number between 0 and 5 that you can then add to 10.
つまり、10 から 15 の範囲の値(両端を含む) を得るためには、 0 から 5 の範囲の乱数を求めて、それに 10 を加えます。
my $number = 10 + int rand( 15-10+1 ); # ( 10,11,12,13,14, or 15 )
Hence you derive the following simple function to abstract that. It selects a random integer between the two given integers (inclusive), For example: random_int_between(50,120)
.
従って、これを抽象化するために以下のサンプル関数を導き出します。 これは与えられた二つの整数を含む範囲のランダムな整数を選択します。 例えば: random_int_between(50,120)
sub random_int_between {
my($min, $max) = @_;
# Assumes that the two arguments are integers themselves!
return $min if $min == $max;
($min, $max) = ($max, $min) if $min > $max;
return $min + int rand(1 + $max - $min);
}
データ:日付¶
その年の何日目であるかを知るには?¶
The day of the year is in the list returned by the localtime
function. Without an argument localtime
uses the current time.
その年の何日目かは localtime
関数から返されるリストにあります。 引数なしの localtime
は現在時刻を使います。
my $day_of_year = (localtime)[7];
The POSIX
module can also format a date as the day of the year or week of the year.
POSIX
モジュールも日付をその年の何日目か、または何週目かに整形します。
use POSIX qw/strftime/;
my $day_of_year = strftime "%j", localtime;
my $week_of_year = strftime "%W", localtime;
To get the day of year for any date, use POSIX
's mktime
to get a time in epoch seconds for the argument to localtime
.
任意の日付に対してその年の何日目かを得るには、localtime の引数から 紀元からの秒数を求めるために、POSIX
の mktime
を使います。
use POSIX qw/mktime strftime/;
my $week_of_year = strftime "%W",
localtime( mktime( 0, 0, 0, 18, 11, 87 ) );
You can also use Time::Piece
, which comes with Perl and provides a localtime
that returns an object:
Perl と共に配布されていて、オブジェクトを返す localtime
を提供する Time::Piece
も使えます:
use Time::Piece;
my $day_of_year = localtime->yday;
my $week_of_year = localtime->week;
The Date::Calc
module provides two functions to calculate these, too:
Date::Calc
モジュールもこれらを計算する二つの関数を提供します:
use Date::Calc;
my $day_of_year = Day_of_Year( 1987, 12, 18 );
my $week_of_year = Week_of_Year( 1987, 12, 18 );
現在の世紀や千年紀を知るには?¶
Use the following simple functions:
以下の単純な関数を使ってください:
sub get_century {
return int((((localtime(shift || time))[5] + 1999))/100);
}
sub get_millennium {
return 1+int((((localtime(shift || time))[5] + 1899))/1000);
}
On some systems, the POSIX
module's strftime()
function has been extended in a non-standard way to use a %C
format, which they sometimes claim is the "century". It isn't, because on most such systems, this is only the first two digits of the four-digit year, and thus cannot be used to determine reliably the current century or millennium.
システムによっては、POSIX
モジュールの strftime()
関数が 非標準の方法で %C
フォーマット("century"だと主張されることがあります)を 使うように拡張されているかもしれません。 これは世紀ではありません。 なぜならこのようなシステムのほとんどでは、 これは 4 桁の年の上位 2 桁を示しているだけなので、 現在の世紀や千年紀を決定する信頼できる方法ではありません。
二つの日付文字列を比較するには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
You could just store all your dates as a number and then subtract. Life isn't always that simple though.
日付を単に数値として保管して、それから引き算することもできます。 しかし、人生はいつもこんな風に単純とは限りません。
The Time::Piece
module, which comes with Perl, replaces localtime
with a version that returns an object. It also overloads the comparison operators so you can compare them directly:
Perl と共に配布されている Time::Piece
モジュールは、localtime
を オブジェクトを返すものに置き換えます。 これはまた比較演算子をオーバーライドするので直接比較できます:
use Time::Piece;
my $date1 = localtime( $some_time );
my $date2 = localtime( $some_other_time );
if( $date1 < $date2 ) {
print "The date was in the past\n";
}
You can also get differences with a subtraction, which returns a Time::Seconds
object:
差分を引き算で得ることもでき、結果は Time::Seconds
オブジェクトに なります:
my $diff = $date1 - $date2;
print "The difference is ", $date_diff->days, " days\n";
If you want to work with formatted dates, the Date::Manip
, Date::Calc
, or DateTime
modules can help you.
フォーマットされた日付に対して作業したい場合は、Date::Manip
, Date::Calc
, DateTime
といったモジュールが助けになるかもしれません。
文字列を受け取って、それを紀元からの経過秒数に変換するには?¶
If it's a regular enough string that it always has the same format, you can split it up and pass the parts to timelocal
in the standard Time::Local
module. Otherwise, you should look into the Date::Calc
, Date::Parse
, and Date::Manip
modules from CPAN.
もしそれが常に同じ書式である十分に標準的な文字列であれば、それを分割して、 その部分部分を標準の Time::Local モジュールの timelocal
に渡せます。 さもなければ、CPAN にある Date::Calc
, Date::Parse
, Date::Manip
モジュールを見るべきでしょう。
ユリウス日を求めるには?¶
(contributed by brian d foy and Dave Cross)
(brian d foy と Dave Cross によって寄贈されました)
You can use the Time::Piece
module, part of the Standard Library, which can convert a date/time to a Julian Day:
日付・時刻をユリウス日に変換できる、標準ライブラリの一部である Time::Piece
モジュールを使えます:
$ perl -MTime::Piece -le 'print localtime->julian_day'
2455607.7959375
Or the modified Julian Day:
あるいは準ユリウス日にも変換できます:
$ perl -MTime::Piece -le 'print localtime->mjd'
55607.2961226851
Or even the day of the year (which is what some people think of as a Julian day):
あるいは年の何日目か(これがユリウス日だと考える人もいます)にも変換できます:
$ perl -MTime::Piece -le 'print localtime->yday'
45
You can also do the same things with the DateTime
module:
DateTime
モジュールで同じことをすることもできます:
$ perl -MDateTime -le'print DateTime->today->jd'
2453401.5
$ perl -MDateTime -le'print DateTime->today->mjd'
53401
$ perl -MDateTime -le'print DateTime->today->doy'
31
You can use the Time::JulianDay
module available on CPAN. Ensure that you really want to find a Julian day, though, as many people have different ideas about Julian days (see http://www.hermetic.ch/cal_stud/jdn.htm for instance):
CPAN にある Time::JulianDay
モジュールが使えます。 しかし、本当にユリウス日がほしいのか確認してください; 多くの人々がユリウス日に関して異なる考え方を持っています。 例としては、http://www.hermetic.ch/cal_stud/jdn.htm を参照してください。
$ perl -MTime::JulianDay -le 'print local_julian_day( time )'
55608
昨日の日付を得るには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
To do it correctly, you can use one of the Date
modules since they work with calendars instead of times. The DateTime
module makes it simple, and give you the same time of day, only the day before, despite daylight saving time changes:
これを正しくするためには、時刻ではなくカレンダーで動作するため、 Date
モジュールの一つを使えます。 DateTime
モジュールは単純で、夏時間に関わらず、前日の同じ時刻を返します:
use DateTime;
my $yesterday = DateTime->now->subtract( days => 1 );
print "Yesterday was $yesterday\n";
You can also use the Date::Calc
module using its Today_and_Now
function.
Date::Calc
モジュールの Today_and_Now
関数を使うこともできます。
use Date::Calc qw( Today_and_Now Add_Delta_DHMS );
my @date_time = Add_Delta_DHMS( Today_and_Now(), -1, 0, 0, 0 );
print "@date_time\n";
Most people try to use the time rather than the calendar to figure out dates, but that assumes that days are twenty-four hours each. For most people, there are two days a year when they aren't: the switch to and from summer time throws this off. For example, the rest of the suggestions will be wrong sometimes:
ほとんどの人は日付を計算するのにカレンダーではなく時刻を使おうとしますが、 これは 1 日が 24 時間であることを仮定しています。 ほとんどの人々にとって、そうではない日が 2 日あります: 夏時間が始まる日と終わる日はこれを狂わせます。 例えば、残りの提案はときどき間違っています:
Starting with Perl 5.10, Time::Piece
and Time::Seconds
are part of the standard distribution, so you might think that you could do something like this:
Perl 5.10 から、Time::Piece
と Time::Seconds
は標準配布の 一部になったので、以下のようにすることを考えるかもしれません:
use Time::Piece;
use Time::Seconds;
my $yesterday = localtime() - ONE_DAY; # WRONG
print "Yesterday was $yesterday\n";
The Time::Piece
module exports a new localtime
that returns an object, and Time::Seconds
exports the ONE_DAY
constant that is a set number of seconds. This means that it always gives the time 24 hours ago, which is not always yesterday. This can cause problems around the end of daylight saving time when there's one day that is 25 hours long.
Time::Piece
モジュールは、オブジェクトを返す新しい localtime
を エクスポートし、Time::Seconds
は秒数を示す ONE_DAY
定数を エクスポートします。 これは常に 24 時間前を意味し、常に昨日というわけではありません。 これは、夏時間の終わりに 1 日が 25 時間ある時に問題があります。
You have the same problem with Time::Local
, which will give the wrong answer for those same special cases:
Time::Local
にも同じ問題があり、同じ特別な状況では間違った答えを 返します:
# contributed by Gunnar Hjalmarsson
use Time::Local;
my $today = timelocal 0, 0, 12, ( localtime )[3..5];
my ($d, $m, $y) = ( localtime $today-86400 )[3..5]; # WRONG
printf "Yesterday: %d-%02d-%02d\n", $y+1900, $m+1, $d;
Perl には 2000 年問題や 2038 年問題があるのですか? Perl は 2000 年対応ですか?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
Perl itself never had a Y2K problem, although that never stopped people from creating Y2K problems on their own. See the documentation for localtime
for its proper use.
Perl 自身には決して Y2K 問題はありませんが、人々が Y2K 問題を自身で 作り出すのを止めることはしません。 正しい使い方については localtime
の文書を参照してください。
Starting with Perl 5.12, localtime
and gmtime
can handle dates past 03:14:08 January 19, 2038, when a 32-bit based time would overflow. You still might get a warning on a 32-bit perl
:
Perl 5.12 から、localtime
と gmtime
は 32 ビットベースの時刻が オーバーフローする 2038 年 1 月 19 日 03:14:08 以降の日付も 扱えるようになりました。 32 ビットの perl
では警告が出るかもしれません:
% perl5.12 -E 'say scalar localtime( 0x9FFF_FFFFFFFF )'
Integer overflow in hexadecimal number at -e line 1.
Wed Nov 1 19:42:39 5576711
On a 64-bit perl
, you can get even larger dates for those really long running projects:
64 ビットの perl
では、本当に長いプロジェクトよりも大きい日付も 得られます:
% perl5.12 -E 'say scalar gmtime( 0x9FFF_FFFFFFFF )'
Thu Nov 2 00:42:39 5576711
You're still out of luck if you need to keep track of decaying protons though.
しかし、これでも陽子の崩壊を記録する必要があるならうまくいきません。
データ: 文字列¶
入力を検査するには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
There are many ways to ensure that values are what you expect or want to accept. Besides the specific examples that we cover in the perlfaq, you can also look at the modules with "Assert" and "Validate" in their names, along with other modules such as Regexp::Common
.
値があなたの予測している、または受け入れたいものであることを保証するには 多くの方法があります。 perlfaq でカバーする特定の例の他に、名前に "Assert" や "Validate" がある モジュールや、Regexp::Common
のようなその他のモジュールを 見ることもできます。
Some modules have validation for particular types of input, such as Business::ISBN
, Business::CreditCard
, Email::Valid
, and Data::Validate::IP
.
Business::ISBN
, Business::CreditCard
, Email::Valid
, Data::Validate::IP
のように、特定の種類の入力を検査するための モジュールもあります。
文字列のアンエスケープ (unescape)をするには?¶
It depends just what you mean by "escape". URL escapes are dealt with in perlfaq9. Shell escapes with the backslash (\
) character are removed with
それはあなたのいう「エスケープ」がなんであるかによります。 URL のエスケープは perlfaq9 で扱っています。 バックスラッシュによるシェルエスケープは以下のようにして取り除きます:
s/\\(.)/$1/g;
This won't expand "\n"
or "\t"
or any other special escapes.
これは \n
だとか \t
、あるいはその他の特殊なエスケープを展開しません。
キャラクタの連続した組を取り除くには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
You can use the substitution operator to find pairs of characters (or runs of characters) and replace them with a single instance. In this substitution, we find a character in (.)
. The memory parentheses store the matched character in the back-reference \g1
and we use that to require that the same thing immediately follow it. We replace that part of the string with the character in $1
.
文字の組(または文字の並び)を探して、それを一つの実体に置き換えるには 置換演算子が使えます。 この置換で、(.)
で一文字が見付かります。 記憶用のかっこはマッチングした文字を後方参照 \g1
に保管し、 同じ文字を直後に要求するために使います。 文字列の一部を $1
にある文字で置き換えます。
s/(.)\g1/$1/g;
We can also use the transliteration operator, tr///
. In this example, the search list side of our tr///
contains nothing, but the c
option complements that so it contains everything. The replacement list also contains nothing, so the transliteration is almost a no-op since it won't do any replacements (or more exactly, replace the character with itself). However, the s
option squashes duplicated and consecutive characters in the string so a character does not show up next to itself
文字変換演算子 tr///
も使えます。 この例では、tr///
の検索リスト側は何も入っていませんが、c
オプションが ついているので全てが含まれます。 置き換えリスト側にも何も入っていないので、文字変換はほとんど何もしません (より厳密には、文字はその文字自身に置き換えられます)。 しかし、s
オプションは文字列中の重複していて連続した文字を 1 文字に 短縮するので、次に同じ文字がある文字は表示されません:
my $str = 'Haarlem'; # in the Netherlands
$str =~ tr///cs; # Now Harlem, like in New York
文字列中にある関数呼び出しを展開するには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
This is documented in perlref, and although it's not the easiest thing to read, it does work. In each of these examples, we call the function inside the braces used to dereference a reference. If we have more than one return value, we can construct and dereference an anonymous array. In this case, we call the function in list context.
これは perlref に文書化されていて、もっとも読みやすいものでは ありませんが、動きます。 これらの例のそれぞれにおいて、大かっこの内側の関数はリファレンスを デリファレンスするために呼び出します。 もし複数の返り値がある場合、無名配列を構築して、デリファレンスします。 この場合、関数をリストコンテキストで呼び出します。
print "The time values are @{ [localtime] }.\n";
If we want to call the function in scalar context, we have to do a bit more work. We can really have any code we like inside the braces, so we simply have to end with the scalar reference, although how you do that is up to you, and you can use code inside the braces. Note that the use of parens creates a list context, so we need scalar
to force the scalar context on the function:
スカラコンテキストで関数を呼び出したい場合、もう少し作業が必要です。 実際に置きたいどんなコードでも中かっこの中に置けるので、 (それをどのようにするかはあなた次第で、中かっこのなかのコードを使えますが) 単にスカラリファレンスで終了する必要があります。 かっこはリストコンテキストを作成するので、関数内でスカラコンテキストを 強制するために scalar
が必要であることに注意してください:
print "The time is ${\(scalar localtime)}.\n"
print "The time is ${ my $x = localtime; \$x }.\n";
If your function already returns a reference, you don't need to create the reference yourself.
関数がすでにリファレンスを返す場合、自分でリファレンスを作る必要は ありません。
sub timestamp { my $t = localtime; \$t }
print "The time is ${ timestamp() }.\n";
The Interpolation
module can also do a lot of magic for you. You can specify a variable name, in this case E
, to set up a tied hash that does the interpolation for you. It has several other methods to do this as well.
Interpolation
モジュールもまたあなたのために多くの魔法を使います。 展開を行う tie されたハッシュを設定するための変数名(この場合は E
)を 指定できます。 同じようにこれを行うその他のいくつかのメソッドを持っています。
use Interpolation E => 'eval';
print "The time values are $E{localtime()}.\n";
In most cases, it is probably easier to simply use string concatenation, which also forces scalar context.
ほとんどの場合、文字列連結を使ってスカラコンテキストに強制するほうが おそらくより簡単です。
print "The time is " . localtime() . ".\n";
何かがマッチしている/ネストしているということを検出するには?¶
This isn't something that can be done in one regular expression, no matter how complicated. To find something between two single characters, a pattern like /x([^x]*)x/
will get the intervening bits in $1. For multiple ones, then something more like /alpha(.*?)omega/
would be needed. But none of these deals with nested patterns. For balanced expressions using (
, {
, [
or <
as delimiters, use the CPAN module Regexp::Common, or see "(??{ code })" in perlre. For other cases, you'll have to write a parser.
これは一つの正規表現で解決できないほどの複雑な問題なのです。 単一のキャラクター二つに囲まれた何かを見つけだすには、 /x([^x]*)x/
といったパターンを使えば $1 に検査の結果が得られるでしょう。 複数キャラクターに囲まれたものの場合は、 /alpha(.*?)omega/
のようなパターンが必要となるでしょう。 しかし、ネストしたパターンを扱うようなものはありませんし、できません。 (
, {
, [
, <
のいずれかのバランス表現をデリミタとして 使っている場合、CPAN にある Regexp::Common モジュールを使うか、 "(??{ code })" in perlre を参照してください。 その他の場合では、パーサーを書く必要があります。
If you are serious about writing a parser, there are a number of modules or oddities that will make your life a lot easier. There are the CPAN modules Parse::RecDescent
, Parse::Yapp
, and Text::Balanced
; and the byacc
program. Starting from perl 5.8 the Text::Balanced
is part of the standard distribution.
もしまじめにパーザを作ろうと考えているのなら、 それを手助けしてくれるようなモジュールやその他のプログラムがあります。 CPAN には Parse::RecDescent
, Parse::Yapp
, Text::Balanced
がありますし、byacc
プログラムもあります。 perl 5.8 から、Text::Balanced
は標準配布の一部になりました。
One simple destructive, inside-out approach that you might try is to pull out the smallest nesting parts one at a time:
単純で破壊的な inside-out アプローチもあります。 これは以下のようにして一度に最小のネスト部分を取り出そうというものです。
while (s/BEGIN((?:(?!BEGIN)(?!END).)*)END//gs) {
# do something with $1
}
A more complicated and sneaky approach is to make Perl's regular expression engine do it for you. This is courtesy Dean Inada, and rather has the nature of an Obfuscated Perl Contest entry, but it really does work:
より複雑で巧妙なやり方に Perl の正規表現エンジンを使うというものがあります。 これは Dean Inada によるもので Obfuscated Perl コンテストに エントリされるような代物ですが、正しく働きます:
# $_ contains the string to parse
# BEGIN and END are the opening and closing markers for the
# nested text.
# $_ には解析対象の文字列があります
# BEGINとENDはネストしたテキストの開始と終了とを行います。
@( = ('(','');
@) = (')','');
($re=$_)=~s/((BEGIN)|(END)|.)/$)[!$3]\Q$1\E$([!$2]/gs;
@$ = (eval{/$re/},$@!~/unmatched/i);
print join("\n",@$[0..$#$]) if( $$[-1] );
文字列をひっくり返すには?¶
Use reverse()
in scalar context, as documented in "reverse" in perlfunc.
"reverse" in perlfunc で説明されているように、スカラコンテキストで reverse()
を使います。
$reversed = reverse $string;
文字列中にあるタブを展開するには?¶
You can do it yourself:
以下のようにしてできます:
1 while $string =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
Or you can just use the Text::Tabs
module (part of the standard Perl distribution).
あるいは、ただ単に Text::Tabs
モジュール(標準 Perl 配布キットの一部です)を 使ってもできます。
use Text::Tabs;
@expanded_lines = expand(@lines_with_tabs);
段落を整形するには?¶
Use Text::Wrap
(part of the standard Perl distribution):
Text::Wrap
(標準 Perl 配布キットの一部です)を使います。
use Text::Wrap;
print wrap("\t", ' ', @paragraphs);
The paragraphs you give to Text::Wrap
should not contain embedded newlines. Text::Wrap
doesn't justify the lines (flush-right).
Text::Wrap
に与える段落には埋め込みの改行があってはいけません。 Text::Wrap
は行を均等割り付けしません(左寄せします)。
Or use the CPAN module Text::Autoformat
. Formatting files can be easily done by making a shell alias, like so:
または CPAN の Text::Autoformat
モジュールを使ってください。 ファイルの整形は以下のようにシェルエイリアスを作ることによって 簡単に実現できます:
alias fmt="perl -i -MText::Autoformat -n0777 \
-e 'print autoformat $_, {all=>1}' $*"
See the documentation for Text::Autoformat
to appreciate its many capabilities.
その多くの能力を評価するために、Text::Autoformat
の文書を 参照してください。
文字列の最初の N 文字にアクセスしたり、それを変更するには?¶
You can access the first characters of a string with substr(). To get the first character, for example, start at position 0 and grab the string of length 1.
文字列の先頭の文字へは substr() でアクセスできます。 例えば、最初の文字を得るには、位置 0 から始めて、長さ 1 の文字列を 取得します。
$string = "Just another Perl Hacker";
$first_char = substr( $string, 0, 1 ); # 'J'
To change part of a string, you can use the optional fourth argument which is the replacement string.
文字列の一部を変換するために、省略可能な 4 番目の引数として置き換える 文字列を指定できます。
substr( $string, 13, 4, "Perl 5.8.0" );
You can also use substr() as an lvalue.
substr() を左辺値として使うこともできます。
substr( $string, 13, 4 ) = "Perl 5.8.0";
何かの N 番目のものを変更するには?¶
You have to keep track of N yourself. For example, let's say you want to change the fifth occurrence of "whoever"
or "whomever"
into "whosoever"
or "whomsoever"
, case insensitively. These all assume that $_ contains the string to be altered.
自分で N 番目の記録を取る必要があります。 例えば、(大小文字の違いを無視して) 5 番目に現れた "whoever"
か "whomever"
を "whosoever"
か "whomsoever"
に変更したいと考えているとしましょう。 以下は全て $_ に変更したい文字列が入っているものとします。
$count = 0;
s{((whom?)ever)}{
++$count == 5 # is it the 5th?
? "${2}soever" # yes, swap
: $1 # renege and leave it there
}ige;
In the more general case, you can use the /g
modifier in a while
loop, keeping count of matches.
もっと一般的なケースでは、while
ループの中で /g
修飾子を使ってマッチの数を数えることもできます。
$WANT = 3;
$count = 0;
$_ = "One fish two fish red fish blue fish";
while (/(\w+)\s+fish\b/gi) {
if (++$count == $WANT) {
print "The third fish is a $1 one.\n";
}
}
That prints out: "The third fish is a red one."
You can also use a repetition count and repeated pattern like this:
これは "The third fish is a red one."
のように出力します。 以下のようにパターンの繰り返し回数を指定するやり方もあります:
/(?:\w+\s+fish\s+){2}(\w+)\s+fish/i;
ある文字列の中に存在する部分文字列が何個あるのかを数えるには?¶
There are a number of ways, with varying efficiency. If you want a count of a certain single character (X) within a string, you can use the tr///
function like so:
様々な効率を持った、いろいろなやり方があります。 文字列中に存在しているある単一キャラクター (X) の数を数えたいのであれば、 tr///
関数を使って次のようにできます:
$string = "ThisXlineXhasXsomeXx'sXinXit";
$count = ($string =~ tr/X//);
print "There are $count X characters in the string";
This is fine if you are just looking for a single character. However, 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 global pattern match. For example, let's count negative integers:
これは単一キャラクターを対象にするのであればちょうどいいものですが、 大きな文字列中の、複数キャラクターから構成される部分文字列の数を 数えようとしても、tr///
はうまく動作しません。 ここで可能なのは、グローバルなパターンマッチを while() で囲んでしまうという ものです。たとえば、負の数を数えるのならこうします:
$string = "-9 55 48 -2 23 -76 4 14 -44";
while ($string =~ /-\d+/g) { $count++ }
print "There are $count negative numbers in the string";
Another version uses a global match in list context, then assigns the result to a scalar, producing a count of the number of matches.
もう一つのバージョンでは、リストコンテキストでグローバルマッチングを 使って、その結果をスカラに代入することで、マッチングした数を数えます。
$count = () = $string =~ /-\d+/g;
一行にあるすべての単語をキャピタライズするには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
Damian Conway's Text::Autoformat handles all of the thinking for you.
Damian Conway による Text::Autoformat は、考えるべき全てのことを 処理してくれます:
use Text::Autoformat;
my $x = "Dr. Strangelove or: How I Learned to Stop ".
"Worrying and Love the Bomb";
print $x, "\n";
for my $style (qw( sentence title highlight )) {
print autoformat($x, { case => $style }), "\n";
}
How do you want to capitalize those words?
これらの単語のキャピタライズはどうしたいですか?
FRED AND BARNEY'S LODGE # all uppercase
Fred And Barney's Lodge # title case
Fred and Barney's Lodge # highlight case
It's not as easy a problem as it looks. How many words do you think are in there? Wait for it... wait for it.... If you answered 5 you're right. Perl words are groups of \w+
, but that's not what you want to capitalize. How is Perl supposed to know not to capitalize that s
after the apostrophe? You could try a regular expression:
これは見た目ほど簡単な問題ではありません。 これらにはいくつの単語があると思いますか? 考え中…考え中…。 もし 5 と答えたなら、あなたは正しいです。 Perl での単語は \w+
の集合ですが、これはあなたが キャピタライズしたいものではありません。 アポストロフィの後の s
はキャピタライズしないように Perl に 知らせるには? 正規表現に挑戦してみましょう:
$string =~ s/ (
(^\w) #at the beginning of the line
| # or
(\s\w) #preceded by whitespace
)
/\U$1/xg;
$string =~ s/([\w']+)/\u\L$1/g;
Now, what if you don't want to capitalize that "and"? Just use Text::Autoformat and get on with the next problem. :)
ここで、"and" をキャピタライズしないようにするには? Text::Autoformat を使って、次の問題に取り組んでください :)
(とある文字)の内側にある時を除き、(とある文字)で終端されている文字列を分割するには?¶
Several modules can handle this sort of parsing--Text::Balanced
, Text::CSV
, Text::CSV_XS
, and Text::ParseWords
, among others.
いくつかのモジュールがこのようなパースを扱います-- Text::Balanced
, Text::CSV
, Text::CSV_XS
, Text::ParseWords
などです。
Take the example case of trying to split a string that is comma-separated into its different fields. You can't use split(/,/)
because you shouldn't split if the comma is inside quotes. For example, take a data line like this:
カンマで分割された文字列を別々のフィールドに置くような例を 考えてみましょう。 ここで split(/,/)
を使うことはできません。 なぜなら、クォートの内側にあるカンマで分割すべきではないからです。 例えば以下のようなデータを考えてみましょう。
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 problem. Thankfully, we have Jeffrey Friedl, author of Mastering Regular Expressions, to handle these for us. He suggests (assuming your string is contained in $text
):
クォートの制約のためにこれは実に複雑な問題です。 ありがたいことに、私たちには Mastering Regular Expressions の著者でもあり、 この問題を私たちのために扱ってくれる Jeffrey Friedl がいます。 彼の提案はこうです(文字列が $text
にあると仮定しています):
@new = ();
push(@new, $+) while $text =~ m{
"([^\"\\]*(?:\\.[^\"\\]*)*)",? # groups the phrase inside the quotes
| ([^,]+),?
| ,
}gx;
push(@new, undef) if substr($text,-1,1) eq ',';
If you want to represent quotation marks inside a quotation-mark-delimited field, escape them with backslashes (eg, "like \"this\""
.
クォーテーションマークで終端されたフィールドの中で クォーテーションマークを表現したいのならば、 それをバックスラッシュで("like \"this\""
のように)エスケープしてください。
Alternatively, the Text::ParseWords
module (part of the standard Perl distribution) lets you say:
あるいは、Text::PaserWords
モジュール(標準 Perl 配布の一部です)を 使ってこうします:
use Text::ParseWords;
@new = quotewords(",", 0, $text);
文字列の先頭や末尾にある空白を剥ぎ取るには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
A substitution can do this for you. For a single line, you want to replace all the leading or trailing whitespace with nothing. You can do that with a pair of substitutions:
置換を使うことで行えます。 1 行では、先頭か末尾のどちらかの空白全てを削除します。 2 つの置換でこれが行えます:
s/^\s+//;
s/\s+$//;
You can also write that as a single substitution, although it turns out the combined statement is slower than the separate ones. That might not matter to you, though:
これを 1 回の置換で書くこともできますが、組み合わせた文は分かれている 文よりも遅くなります。 しかし、それはあなたには問題がないかもしれません:
s/^\s+|\s+$//g;
In this regular expression, the alternation matches either at the beginning or the end of the string since the anchors have a lower precedence than the alternation. With the /g
flag, the substitution makes all possible matches, so it gets both. Remember, the trailing newline matches the \s+
, and the $
anchor can match to the absolute end of the string, so the newline disappears too. Just add the newline to the output, which has the added benefit of preserving "blank" (consisting entirely of whitespace) lines which the ^\s+
would remove all by itself:
この正規表現において、アンカーは the alternation より低い優先順位を 持つので、the alternation は文字列の先頭か末尾にマッチングします。 /g
フラグが付いていることにより、可能な全てのマッチングについて置換が 行われるので、先頭と末尾の両方で行われます。 引き続く改行は \s+
にマッチングし、$
アンカーは文字列の絶対的な 末尾にマッチングするので、改行も消えることを忘れないでください。 単に出力に改行を追加することで、^\s+
がすべて削除してしまう「空の」 (空白だけからなる)行を保存する利点が追加されます:
while( <> ) {
s/^\s+|\s+$//g;
print "$_\n";
}
For a multi-line string, you can apply the regular expression to each logical line in the string by adding the /m
flag (for "multi-line"). With the /m
flag, the $
matches before an embedded newline, so it doesn't remove it. This pattern still removes the newline at the end of the string:
複数行の文字列に対しては、/m
("multi-line") フラグを追加することにより、 文字列中の論理行毎に正規表現を適用できます。 /m
フラグをつけると、$
組み込まれた改行の 前に マッチングするので、 これを取り除けません。 このパターンで文字列の末尾の改行は取り除けます:
$string =~ s/^\s+|\s+$//gm;
Remember that lines consisting entirely of whitespace will disappear, since the first part of the alternation can match the entire string and replace it with nothing. If you need to keep embedded blank lines, you have to do a little more work. Instead of matching any whitespace (since that includes a newline), just match the other whitespace:
空白だけからなる文字列は、置換の最初の部分が文字列全体にマッチングして、 それを空文字列に置き換えてしまうので、消えてしまうことに注意してください。 もし組み込まれている空行を保存したいなら、さらにもう少し作業をする必要が あります。 全ての空白(改行を含みます)にマッチングさせる代わりに、単にその他の 空白にマッチングさせます:
$string =~ s/^[\t\f ]+|[\t\f ]+$//mg;
文字列に空白をパッディングしたり、数値にゼロをパッディングしたりするには?¶
In the following examples, $pad_len
is the length to which you wish to pad the string, $text
or $num
contains the string to be padded, and $pad_char
contains the padding character. You can use a single character string constant instead of the $pad_char
variable if you know what it is in advance. And in the same way you can use an integer in place of $pad_len
if you know the pad length in advance.
以下に挙げる例で、$pad_len
はパッディングしたい文字列の長さです。 $text
や $num
は文字列にパッディングの対象となる内容を保持していて、 $pad_char
がパッディングに使いたいキャラクターを保持しています。 やっていることがわかっているのなら、$pad_char
という変数の代わりに一 文字のキャラクター文字列を使うこともできます。 そして同様に、パッディングしたい長さが予め分かっているなら、 $pad_len
に整数値を指定することも出来ます。
The simplest method uses the sprintf
function. It can pad on the left or right with blanks and on the left with zeroes and it will not truncate the result. The pack
function can only pad strings on the right with blanks and it will truncate the result to a maximum length of $pad_len
.
最も単純なやり方は sprintf
関数を使うというものです。 この関数は文字列の左や右にパッディングを行ったり、0 を左に置いたりする ことができます。 pack
関数は文字列の右側に空白でパッディングすることと、 結果の最大長を $pad_len
に切り詰めることだけができます。
# Left padding a string with blanks (no truncation):
$padded = sprintf("%${pad_len}s", $text);
$padded = sprintf("%*s", $pad_len, $text); # same thing
# Right padding a string with blanks (no truncation):
$padded = sprintf("%-${pad_len}s", $text);
$padded = sprintf("%-*s", $pad_len, $text); # same thing
# Left padding a number with 0 (no truncation):
$padded = sprintf("%0${pad_len}d", $num);
$padded = sprintf("%0*d", $pad_len, $num); # same thing
# Right padding a string with blanks using pack (will truncate):
$padded = pack("A$pad_len",$text);
If you need to pad with a character other than blank or zero you can use one of the following methods. They all generate a pad string with the x
operator and combine that with $text
. These methods do not truncate $text
.
空白やゼロ以外のキャラクターでパッディングを行いたいのであれば、 以下に挙げるやり方を使うことができます。これらは全て パッディング文字列を x
修飾子で生成して $text
と結合します。 これらのメソッドは $text
を切り詰めません。
Left and right padding with any character, creating a new string:
任意のキャラクターによる左詰めと右詰めを行い、新しい文字列を作ります:
$padded = $pad_char x ( $pad_len - length( $text ) ) . $text;
$padded = $text . $pad_char x ( $pad_len - length( $text ) );
Left and right padding with any character, modifying $text
directly:
任意のキャラクターによる左詰めと右詰めを行い、$text
を直接変更します:
substr( $text, 0, 0 ) = $pad_char x ( $pad_len - length( $text ) );
$text .= $pad_char x ( $pad_len - length( $text ) );
文字列から選択されたカラムを取り出すには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
If you know the columns that contain the data, you can use substr
to extract a single column.
データが含まれている桁が分かっているなら、単一の桁を展開するために substr
が使えます。
my $column = substr( $line, $start_column, $length );
You can use split
if the columns are separated by whitespace or some other delimiter, as long as whitespace or the delimiter cannot appear as part of the data.
桁が空白やその他のデリミタで分けられていて、データの一部としては 空白やデリミタが現れないなら、split
が使えます。
my $line = ' fred barney betty ';
my @columns = split /\s+/, $line;
# ( '', 'fred', 'barney', 'betty' );
my $line = 'fred||barney||betty';
my @columns = split /\|/, $line;
# ( 'fred', '', 'barney', '', 'betty' );
If you want to work with comma-separated values, don't do this since that format is a bit more complicated. Use one of the modules that handle that format, such as Text::CSV
, Text::CSV_XS
, or Text::CSV_PP
.
カンマ区切りの値(CSV)を扱いたい場合は、フォーマットが少し複雑なので これはしないで下さい。 Text::CSV
, Text::CSV_XS
, Text::CSV_PP
のような、この フォーマットを扱うためのモジュールの一つを使ってください。
If you want to break apart an entire line of fixed columns, you can use unpack
with the A (ASCII) format. By using a number after the format specifier, you can denote the column width. See the pack
and unpack
entries in perlfunc for more details.
固定桁の行全体を分解したいなら、unpack
の A (ASCII) フォーマットが 使えます。 フォーマット指定子の後に数値をつけることで、桁数を指定できます。 更なる詳細については perlfunc の pack
と unpack
の項目を 参照してください。
my @fields = unpack( $line, "A8 A8 A8 A16 A4" );
Note that spaces in the format argument to unpack
do not denote literal spaces. If you have space separated data, you may want split
instead.
unpack
のフォーマット引数での空白はリテラルな空白を意味しないことに 注意してください。 もし空白で区切られたデータがあるなら、代わりに split
を使ったほうが いいかもしれません。
文字列の soundex 値を見つけるには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
You can use the Text::Soundex module. If you want to do fuzzy or close matching, you might also try the String::Approx
, and Text::Metaphone
, and Text::DoubleMetaphone
modules.
Text::Soundex モジュールが使えます。 あいまいマッチングや近傍マッチングを行いたいなら、 String::Approx
, Text::Metaphone
, Text::DoubleMetaphone
といった モジュールを試すのも良いでしょう。
テキスト文字列の中にある変数を展開するには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
If you can avoid it, don't, or if you can use a templating system, such as Text::Template
or Template
Toolkit, do that instead. You might even be able to get the job done with sprintf
or printf
:
もし避けることが可能なら、してはいけません; あるいは、Text::Template
や Template
ツールキットのような テンプレートシステムが使えるなら、これらを代わりに使ってください。 sprintf
や printf
を使って作業をこなすことすらできます:
my $string = sprintf 'Say hello to %s and %s', $foo, $bar;
However, for the one-off simple case where I don't want to pull out a full templating system, I'll use a string that has two Perl scalar variables in it. In this example, I want to expand $foo
and $bar
to their variable's values:
しかし、完全なテンプレートシステムを引っ張り出したくないような一度限りの 簡単な場合には、内部に二つの Perl スカラ変数を持つ文字列を使います。 この例では、$foo
と $bar
をその変数の値に展開したいとします:
my $foo = 'Fred';
my $bar = 'Barney';
$string = 'Say hello to $foo and $bar';
One way I can do this involves the substitution operator and a double /e
flag. The first /e
evaluates $1
on the replacement side and turns it into $foo
. The second /e starts with $foo
and replaces it with its value. $foo
, then, turns into 'Fred', and that's finally what's left in the string:
これを行う一つの方法は、置換演算子と二つの /e
フラグを使うものです。 一つ目の /e
は置き換え側の $1
を評価して $foo
に変えます。 二つ目の /e
は $foo
をその値に変えます。 従って、$foo
は 'Fred' に変わって、それが結局最終的に文字列に 残されるものになります:
$string =~ s/(\$\w+)/$1/eeg; # 'Say hello to Fred and Barney'
The /e
will also silently ignore violations of strict, replacing undefined variable names with the empty string. Since I'm using the /e
flag (twice even!), I have all of the same security problems I have with eval
in its string form. If there's something odd in $foo
, perhaps something like @{[ system "rm -rf /" ]}
, then I could get myself in trouble.
/e
は暗黙のうちに struct 違反を無視するので、未定義の変数名を 空文字列に置き換えます。 /e
フラグを (2 回も!) 使っているので、eval
を文字列の形で使うのと 同じセキュリティ問題を全て抱えています。 もし $foo
に(おそらく @{[ system "rm -rf /" ]}
のような)変なものが 入っていたら、トラブルに出会うことになります。
To get around the security problem, I could also pull the values from a hash instead of evaluating variable names. Using a single /e
, I can check the hash to ensure the value exists, and if it doesn't, I can replace the missing value with a marker, in this case ???
to signal that I missed something:
セキュリティ問題を避けるために、変数名を評価するのではなくハッシュから 値を取ってくることもできます。 /e
を一つ使って、ハッシュに値があることを確認し、もしなければ、 値をマーカーに置き換えます; この場合は、???
が何かがおかしいことの 印です;
my $string = 'This has $foo and $bar';
my %Replacements = (
foo => 'Fred',
);
# $string =~ s/\$(\w+)/$Replacements{$1}/g;
$string =~ s/\$(\w+)/
exists $Replacements{$1} ? $Replacements{$1} : '???'
/eg;
print $string;
常にクォーティング "$vars" することの何が悪いの?¶
The problem is that those double-quotes force stringification--coercing numbers and references into strings--even when you don't want them to be strings. Think of it this way: double-quote expansion is used to produce new strings. If you already have a string, why do you need more?
そういったダブルクォートが、強制的に文字列化(stringification)するのが問題で、 たとえそれを望んでいなくても数値やリファレンスが強制的に 文字列に変換されてしまうのです。 このように考えましょう: ダブルクォートは新しい文字列を生成するのに使われる。 もしあなたがすでに文字列を持っているのであれば、使う必要が あるでしょうか?
If you get used to writing odd things like these:
以下の例のような変な書き方をすると:
print "$var"; # BAD
$new = "$old"; # BAD
somefunc("$var"); # BAD
You'll be in trouble. Those should (in 99.8% of the cases) be the simpler and more direct:
あなたはトラブルに巻き込まれることになるでしょう。 これらは(99.8% は)、より単純、かつより直接的に書くべきなのです。
print $var;
$new = $old;
somefunc($var);
Otherwise, besides slowing you down, you're going to break code when the thing in the scalar is actually neither a string nor a number, but a reference:
さもなければ、プログラムを遅くなることのほかにも、スカラが実際には文字列でも 数値でもなくリファレンスであるようなときにあなたのプログラムが おかしくなることになります。
func(\@array);
sub func {
my $aref = shift;
my $oref = "$aref"; # WRONG
}
You can also get into subtle problems on those few operations in Perl that actually do care about the difference between a string and a number, such as the magical ++
autoincrement operator or the syscall() function.
マジカル ++
オートインクリメント演算子や syscall() 関数のような、 文字列と数値の間の違いを実際に気にするような Perl の幾つかの操作において、 微妙な問題に直面するかもしれません。
Stringification also destroys arrays.
文字列化(stringfication)も配列を壊します。
@lines = `command`;
print "@lines"; # WRONG - extra blanks
print @lines; # right
なぜ私の <¶
Here documents are found in perlop. Check for these three things:
文書は perlop にあります。 以下の三つの点を確認してください。
- There must be no space after the << part.
-
(<< パートの後ろに空白があってはいけません。)
- There (probably) should be a semicolon at the end of the opening token
-
(開いているトークンの末尾にセミコロンが置かれているかもしれません。)
- You can't (easily) have any space in front of the tag.
-
(タグの前に任意のスペースを置くことはできません。)
- There needs to be at least a line separator after the end token.
-
(終了トークンの後に少なくとも一つの行区切りが必要です。)
If you want to indent the text in the here document, you can do this:
ヒアドキュメントのテキストでインデントを使いたいのであれば、 以下のようにしてできます:
# all in one
($VAR = <<HERE_TARGET) =~ s/^\s+//gm;
your text
goes here
HERE_TARGET
But the HERE_TARGET must still be flush against the margin. If you want that indented also, you'll have to quote in the indentation.
しかしこの場合も HERE_TARGET は先頭に置かなければなりません。 もしこれもインデントしたいのなら、インデントをクォートする必要があるでしょう。
($quote = <<' FINIS') =~ s/^\s+//gm;
...we will have peace, when you and all your works have
perished--and the works of your dark master to whom you
would deliver us. You are a liar, Saruman, and a corrupter
of men's hearts. --Theoden in /usr/src/perl/taint.c
FINIS
$quote =~ s/\s+--/\n--/;
A nice general-purpose fixer-upper function for indented here documents follows. It expects to be called with a here document as its argument. It looks to see whether each line begins with a common substring, and if so, strips that substring off. Otherwise, it takes the amount of leading whitespace found on the first line and removes that much off each subsequent line.
以下はインデントされたヒアドキュメントのための汎用 fixer-upper 関数です。 この関数は引数にヒアドキュメントを渡されることを期待しています。 これは共通の部分文字列で始まる各行について、 その部分文字列を剥ぎ取るということを行います。 あるいは、最初の行の先頭にある空白を取り、 続く行に対しても同じ様に削除を行います。
sub fix {
local $_ = shift;
my ($white, $leader); # common whitespace and common leading string
if (/^\s*(?:([^\w\s]+)(\s*).*\n)(?:\s*\g1\g2?.*\n)+$/) {
($white, $leader) = ($2, quotemeta($1));
} else {
($white, $leader) = (/^(\s+)/, '');
}
s/^\s*?$leader(?:$white)?//gm;
return $_;
}
This works with leading special strings, dynamically determined:
この関数は先頭にある特別な、動的に決められる文字列に対しても使えます:
$remember_the_main = fix<<' MAIN_INTERPRETER_LOOP';
@@@ int
@@@ runops() {
@@@ SAVEI32(runlevel);
@@@ runlevel++;
@@@ while ( op = (*op->op_ppaddr)() );
@@@ TAINT_NOT;
@@@ return 0;
@@@ }
MAIN_INTERPRETER_LOOP
Or with a fixed amount of leading whitespace, with remaining indentation correctly preserved:
また、先頭にある特定の個数の空白を取り除いて、インデントを 正しく残すようなこともできます:
$poem = fix<<EVER_ON_AND_ON;
Now far ahead the Road has gone,
And I must follow, if I can,
Pursuing it with eager feet,
Until it joins some larger way
Where many paths and errands meet.
And whither then? I cannot say.
--Bilbo in /usr/src/perl/pp_ctl.c
EVER_ON_AND_ON
データ: 配列¶
リストと配列の差とはなんですか?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
A list is a fixed collection of scalars. An array is a variable that holds a variable collection of scalars. An array can supply its collection for list operations, so list operations also work on arrays:
リストとはスカラの固定されたコレクションです。 配列はスカラの変動するコレクションを保持する変数です。 配列は保持しているコレクションをリスト演算に提供できるので、 リスト演算は配列に対しても動作します:
# slices
( 'dog', 'cat', 'bird' )[2,3];
@animals[2,3];
# iteration
foreach ( qw( dog cat bird ) ) { ... }
foreach ( @animals ) { ... }
my @three = grep { length == 3 } qw( dog cat bird );
my @three = grep { length == 3 } @animals;
# supply an argument list
wash_animals( qw( dog cat bird ) );
wash_animals( @animals );
Array operations, which change the scalars, rearranges them, or adds or subtracts some scalars, only work on arrays. These can't work on a list, which is fixed. Array operations include shift
, unshift
, push
, pop
, and splice
.
スカラを変更したり再配置したり加えたり取り去ったりするような配列操作は 配列に対してのみ動作します。 これらは(固定されているので)リストに対しては動作しません。 配列操作は shift
, unshift
, push
, pop
, splice
などです。
An array can also change its length:
配列は長さを変えることもできます:
$#animals = 1; # truncate to two elements
$#animals = 10000; # pre-extend to 10,001 elements
You can change an array element, but you can't change a list element:
配列要素を変更することはできますが、リスト要素を変更することはできません:
$animals[0] = 'Rottweiler';
qw( dog cat bird )[0] = 'Rottweiler'; # syntax error!
foreach ( @animals ) {
s/^d/fr/; # works fine
}
foreach ( qw( dog cat bird ) ) {
s/^d/fr/; # Error! Modification of read only value!
}
However, if the list element is itself a variable, it appears that you can change a list element. However, the list element is the variable, not the data. You're not changing the list element, but something the list element refers to. The list element itself doesn't change: it's still the same variable.
しかし、リスト要素それ自身が変数のとき、リスト要素を変更できるように 見えます。 しかし、リスト要素は変数であって、データではありません。 リスト要素を変更することは出来ませんが、リスト要素が参照しているものは 変更できます。 リスト要素自身は変更できません: 同じ値のままです。
You also have to be careful about context. You can assign an array to a scalar to get the number of elements in the array. This only works for arrays, though:
また、コンテキストに対しても注意する必要があります。 配列の要素数を得るために配列をスカラに代入できます。 これは配列に対してのみ動作します:
my $count = @animals; # only works with arrays
If you try to do the same thing with what you think is a list, you get a quite different result. Although it looks like you have a list on the righthand side, Perl actually sees a bunch of scalars separated by a comma:
同じことを、リストと考えているものに対して実行すると、全く異なった 結果になります。 右側にリストがあるように見えますが、Perl は実際にはカンマで区切られた スカラの塊を見ています:
my $scalar = ( 'dog', 'cat', 'bird' ); # $scalar gets bird
Since you're assigning to a scalar, the righthand side is in scalar context. The comma operator (yes, it's an operator!) in scalar context evaluates its lefthand side, throws away the result, and evaluates it's righthand side and returns the result. In effect, that list-lookalike assigns to $scalar
it's rightmost value. Many people mess this up because they choose a list-lookalike whose last element is also the count they expect:
スカラに代入しているので、右側はスカラコンテキストです。 スカラコンテキストでのカンマ演算子 (ええ、これは演算子です!) は左側を 評価して、その結果を捨てて、右側を評価して、結果を返します。 事実上、$scalar
へのリストに見えるものの代入は、一番右の値です。 多くの人々は、最後の要素が想定している要素数と同じになっている リストのように見えるものを選択するので、これに混乱します:
my $scalar = ( 1, 2, 3 ); # $scalar gets 3, accidentally
$array[1] と @array[1] との間の違いはなんですか?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
The difference is the sigil, that special character in front of the array name. The $
sigil means "exactly one item", while the @
sigil means "zero or more items". The $
gets you a single scalar, while the @
gets you a list.
違いは印 (sigil) で、配列名の前にある特殊文字です。 $
印は「正確に一つのアイテム」を意味し、@
印は「0 個以上のアイテム」を 意味します。 $
では一つのスカラを得られ、@
ではリストを得られます。
The confusion arises because people incorrectly assume that the sigil denotes the variable type.
人々は間違って印が変数の型を示していると仮定するために混乱が発生します。
The $array[1]
is a single-element access to the array. It's going to return the item in index 1 (or undef if there is no item there). If you intend to get exactly one element from the array, this is the form you should use.
$array[1]
は配列の一つの要素です。 これは添え字 1 のアイテム(またはそこにアイテムがなければ undef) を 返します。 もし配列から一つだけの要素を取り出そうとするなら、これが使うべきものです。
The @array[1]
is an array slice, although it has only one index. You can pull out multiple elements simultaneously by specifying additional indices as a list, like @array[1,4,3,0]
.
@array[1]
は配列スライスですが、一つの添え字しかありません。 @array[1,4,3,0]
のように追加の添え字をリストとして指定することで、複数の 要素を同時に引き出せます。
Using a slice on the lefthand side of the assignment supplies list context to the righthand side. This can lead to unexpected results. For instance, if you want to read a single line from a filehandle, assigning to a scalar value is fine:
代入の左側でスライスを使うことで、右側にリストコンテキストを提供します。 これは予想外の結果を引き起こすことがあります。 例えば、もしファイルハンドルから 1 行を読み込みたいとき、スカラ値への 代入はうまくいきます:
$array[1] = <STDIN>;
However, in list context, the line input operator returns all of the lines as a list. The first line goes into @array[1]
and the rest of the lines mysteriously disappear:
しかし、リストコンテキストでは、行入力演算子は全ての行をリストとして 返します。 最初の行は @array[1]
に入り、残りの行はどこかに消えてしまします:
@array[1] = <STDIN>; # most likely not what you want
Either the use warnings
pragma or the -w flag will warn you when you use an array slice with a single index.
use warnings
プラグマか -w オプションを使うと、添え字が一つだけの スライスを使ったときに警告されます。
配列やリストにある重複した要素を削除するには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
Use a hash. When you think the words "unique" or "duplicated", think "hash keys".
ハッシュを使ってください。 「ユニーク」や「重複」といった単語を考えたときには、 「ハッシュキー」を考えてください。
If you don't care about the order of the elements, you could just create the hash then extract the keys. It's not important how you create that hash: just that you use keys
to get the unique elements.
要素の順番を気にしないなら、単にハッシュを作ってキーを取り出してください。 どのようにハッシュを作るかは重要ではありません: 単にユニークな要素を取り出すために keys
を使うためです。
my %hash = map { $_, 1 } @array;
# or a hash slice: @hash{ @array } = ();
# or a foreach: $hash{$_} = 1 foreach ( @array );
my @unique = keys %hash;
If you want to use a module, try the uniq
function from List::MoreUtils
. In list context it returns the unique elements, preserving their order in the list. In scalar context, it returns the number of unique elements.
モジュールを使いたいなら、List::MoreUtils
の uniq
関数を 試してみてください。 リストコンテキストでは、リストの順序を保存した形でユニークな要素を返します。 スカラコンテキストでは、ユニークな要素の数を返します。
use List::MoreUtils qw(uniq);
my @unique = uniq( 1, 2, 3, 4, 4, 5, 6, 5, 7 ); # 1,2,3,4,5,6,7
my $unique = uniq( 1, 2, 3, 4, 4, 5, 6, 5, 7 ); # 7
You can also go through each element and skip the ones you've seen before. Use a hash to keep track. The first time the loop sees an element, that element has no key in %Seen
. The next
statement creates the key and immediately uses its value, which is undef
, so the loop continues to the push
and increments the value for that key. The next time the loop sees that same element, its key exists in the hash and the value for that key is true (since it's not 0 or undef
), so the next skips that iteration and the loop goes to the next element.
各要素を調べて、一度見つけたものをスキップすることもできます。 記録をつけるためにハッシュを使います。 ループが最初に要素を見つけると、この要素は %Seen
にキーがありません。 next
文はキーを作り、直ちにその値(undef
)を使うので、 ループは push
を続行し、このキーの値をインクリメントします。 次回にループが同じ要素を見つけると、ハッシュにはそのキーが存在し、 かつ そのキーの値が(0 でも undef
でもないので)真なので、 next は反復をスキップし、ループは次の要素に進みます。
my @unique = ();
my %seen = ();
foreach my $elem ( @array )
{
next if $seen{ $elem }++;
push @unique, $elem;
}
You can write this more briefly using a grep, which does the same thing.
grep を使うことでより簡単に書くこともでき、これは同じことになります。
my %seen = ();
my @unique = grep { ! $seen{ $_ }++ } @array;
リストや配列の内容にある特定の要素があるかどうかを確かめるには?¶
(portions of this answer contributed by Anno Siegel and brian d foy)
(この回答の一部は Anno Siegel と brian d foy によって寄贈されました)
Hearing the word "in" is an indication that you probably should have used a hash, not a list or array, to store your data. Hashes are designed to answer this question quickly and efficiently. Arrays aren't.
ハッシュはこの質問に対する速くて効率の良い解答のために デザインされています。 配列はそうではありません。
That being said, there are several ways to approach this. In Perl 5.10 and later, you can use the smart match operator to check that an item is contained in an array or a hash:
幾つかのやり方があります。 Perl 5.10 以降では、アイテムが配列やハッシュに含まれているかを チェックするのにスマートマッチング演算子が使えます:
use 5.010;
if( $item ~~ @array )
{
say "The array contains $item"
}
if( $item ~~ %hash )
{
say "The hash contains $item"
}
With earlier versions of Perl, you have to do a bit more work. If you are going to make this query many times over arbitrary string values, the fastest way is probably to invert the original array and maintain a hash whose keys are the first array's values:
以前のバージョンの Perl では、もう少し作業が必要です。 この問い合わせを多くのアイテムに対して 行いたいとか、値が任意の文字列である場合には最も速いやり方は元の 配列の逆のものを作って元の配列の値をキーとするようなハッシュを 管理するというものです:
@blues = qw/azure cerulean teal turquoise lapis-lazuli/;
%is_blue = ();
for (@blues) { $is_blue{$_} = 1 }
Now you can check whether $is_blue{$some_color}
. It might have been a good idea to keep the blues all in a hash in the first place.
こうすれば、$is_blue{$some_color}
がどうであるかでチェックできます。 最初の場所で bules にハッシュのすべてを保持させるのはよい考えでしょう。
If the values are all small integers, you could use a simple indexed array. This kind of an array will take up less space:
値のすべてが小さな整数であれば、単純な添え字付き配列を使うことができます。 この種の配列はより少ない場所しか使いません。
@primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);
@is_tiny_prime = ();
for (@primes) { $is_tiny_prime[$_] = 1 }
# or simply @istiny_prime[@primes] = (1) x @primes;
Now you check whether $is_tiny_prime[$some_number].
これで $is_tiny_prime[$some_number] の内容がどうであるかで チェックできます。
If the values in question are integers instead of strings, you can save quite a lot of space by using bit strings instead:
問い合わせる値が文字列ではなく整数であるのならば、ビットストリングを 使うことによって大幅に空間を節約することができます。
@articles = ( 1..10, 150..2000, 2017 );
undef $read;
for (@articles) { vec($read,$_,1) = 1 }
Now check whether vec($read,$n,1)
is true for some $n
.
これで vec($read,$n,1)
が真かどうかで $n
の検査ができます。
These methods guarantee fast individual tests but require a re-organization of the original list or array. They only pay off if you have to test multiple values against the same array.
これらのメソッドは個々のテストの速さが保証されていますが、 元のリストや配列の再構成が必要です。 同じ配列に対して複数の値をテストする必要がある場合にのみ元が取れます。
If you are testing only once, the standard module List::Util
exports the function first
for this purpose. It works by stopping once it finds the element. It's written in C for speed, and its Perl equivalent looks like this subroutine:
一度だけテストする場合、標準モジュール List::Util
がこの目的のために first
関数をエクスポートしています。 これは要素を見つけると停止することで動作します。 速度のために C で書かれていて、これの Perl の等価な処理は、次のサブルーチンの ようになります:
sub first (&@) {
my $code = shift;
foreach (@_) {
return $_ if &{$code}();
}
undef;
}
If speed is of little concern, the common idiom uses grep in scalar context (which returns the number of items that passed its condition) to traverse the entire list. This does have the benefit of telling you how many matches it found, though.
速度が問題ではないなら、一般的な方法は、リスト全体をトラバースするために grep をスカラコンテキストで使う(これで条件をパスしたアイテムの数を返します) ことです。 しかし、これには何回マッチングしたのかを知らせるという利点があります。
my $is_there = grep $_ eq $whatever, @array;
If you want to actually extract the matching elements, simply use grep in list context.
実際にマッチングした要素を展開したい場合は、単にリストコンテキストで grep を使ってください。
my @matches = grep $_ eq $whatever, @array;
二つの配列の差(difference)を求めるには? 二つの配列の共通要素(inter section)を求めるには?¶
Use a hash. Here's code to do both and more. It assumes that each element is unique in a given array:
ハッシュを使います。 以下のプログラム片は質問の両方を行います。 与えられた配列の要素には重複がないと仮定しています。
@union = @intersection = @difference = ();
%count = ();
foreach $element (@array1, @array2) { $count{$element}++ }
foreach $element (keys %count) {
push @union, $element;
push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;
}
Note that this is the symmetric difference, that is, all elements in either A or in B but not in both. Think of it as an xor operation.
これは 対称的差分、つまり、A か B のどちらかにあって、 両方にあることはない全ての要素である、ということに注意してください。 これは xor 操作のようなものと考えてください。
二つの配列や二つのハッシュが等しいかどうかを検査するには?¶
With Perl 5.10 and later, the smart match operator can give you the answer with the least amount of work:
Perl 5.10 以降では、スマートマッチング演算子が最小の作業で答えを 与えてくれます:
use 5.010;
if( @array1 ~~ @array2 )
{
say "The arrays are the same";
}
if( %hash1 ~~ %hash2 ) # doesn't check values!
{
say "The hash keys are the same";
}
The following code works for single-level arrays. It uses a stringwise comparison, and does not distinguish defined versus undefined empty strings. Modify if you have other needs.
以下に挙げる例は一レベルの配列に対して有効です。 これは文字列としての比較を使い、定義済みと未定義の空文字列を区別しません。 必要に応じて修正してください。
$are_equal = compare_arrays(\@frogs, \@toads);
sub compare_arrays {
my ($first, $second) = @_;
no warnings; # silence spurious -w undef complaints
return 0 unless @$first == @$second;
for (my $i = 0; $i < @$first; $i++) {
return 0 if $first->[$i] ne $second->[$i];
}
return 1;
}
For multilevel structures, you may wish to use an approach more like this one. It uses the CPAN module FreezeThaw
:
多重レベル構造に対応するために、あなたは以下のような手段を使いたいと 考えるかもしれません。 ここでは CPAN モジュールの FreezeThaw
を使っています:
use FreezeThaw qw(cmpStr);
@a = @b = ( "this", "that", [ "more", "stuff" ] );
printf "a and b contain %s arrays\n",
cmpStr(\@a, \@b) == 0
? "the same"
: "different";
This approach also works for comparing hashes. Here we'll demonstrate two different answers:
このアプローチはハッシュの比較にも使えます。 以下に二種類の回答をお見せしましょう:
use FreezeThaw qw(cmpStr cmpStrHard);
%a = %b = ( "this" => "that", "extra" => [ "more", "stuff" ] );
$a{EXTRA} = \%b;
$b{EXTRA} = \%a;
printf "a and b contain %s hashes\n",
cmpStr(\%a, \%b) == 0 ? "the same" : "different";
printf "a and b contain %s hashes\n",
cmpStrHard(\%a, \%b) == 0 ? "the same" : "different";
The first reports that both those the hashes contain the same data, while the second reports that they do not. Which you prefer is left as an exercise to the reader.
最初のものは二つのハッシュが同じ内容であると報告しますが、二番目の ものは違うと報告します。
ある条件が真となる最初の配列要素を見つけだすには?¶
To find the first array element which satisfies a condition, you can use the first()
function in the List::Util
module, which comes with Perl 5.8. This example finds the first element that contains "Perl".
条件を満たす最初の配列要素を探すためには、Perl 5.8 から同梱されている List::Util
モジュールの first()
関数が使えます。 この例は "Perl" を含む最初の要素を探します。
use List::Util qw(first);
my $element = first { /Perl/ } @array;
If you cannot use List::Util
, you can make your own loop to do the same thing. Once you find the element, you stop the loop with last.
List::Util
が使えない場合は、同じことをするために自分でループを書きます。 要素が見つかったら、last を使ってループを停止します。
my $found;
foreach ( @array ) {
if( /Perl/ ) { $found = $_; last }
}
If you want the array index, you can iterate through the indices and check the array element at each index until you find one that satisfies the condition.
配列の添え字がほしい場合は、添え字に順番に変えていって、 それぞれの添え字の配列要素をチェックして、条件を満たすものが 見つかるまで繰り返します。
my( $found, $index ) = ( undef, -1 );
for( $i = 0; $i < @array; $i++ ) {
if( $array[$i] =~ /Perl/ ) {
$found = $array[$i];
$index = $i;
last;
}
}
リンク付きリストを扱うには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
Perl's arrays do not have a fixed size, so you don't need linked lists if you just want to add or remove items. You can use array operations such as push
, pop
, shift
, unshift
, or splice
to do that.
Perl の配列は固定のサイズを持たないので、単にアイテムを追加または 削除したいならリンク付きリストは不要です。 そのために push
, pop
, shift
, unshift
, splice
のような 配列操作が使えます。
Sometimes, however, linked lists can be useful in situations where you want to "shard" an array so you have have many small arrays instead of a single big array. You can keep arrays longer than Perl's largest array index, lock smaller arrays separately in threaded programs, reallocate less memory, or quickly insert elements in the middle of the chain.
しかし、ときどき、一つの大きな配列ではなく多くの小さい配列があるために 配列を「共有」したい時にはリンク付きリストは有用かもしれません。 Perl の最大の配列添え字よりも大きい配列を維持したり、スレッドプログラムで より小さい配列を別々にロックしたり、より小さいメモリに再配置したり、 チェーンの中間に素早く要素を挿入したりできます。
Steve Lembark goes through the details in his YAPC::NA 2009 talk "Perly Linked Lists" ( http://www.slideshare.net/lembark/perly-linked-lists ), although you can just use his LinkedList::Single
module.
Steve Lembark は YAPC::NA 2009 の "Perly Linked Lists" ( http://www.slideshare.net/lembark/perly-linked-lists ) で 詳細について話していますが、単に彼の LinkedList::Single
モジュールを 使えます。
循環リストを扱うには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
If you want to cycle through an array endlessly, you can increment the index modulo the number of elements in the array:
配列を無限に循環したいなら、配列の添え字をインクリメントして 要素数の剰余を取ったものを使います:
my @array = qw( a b c );
my $i = 0;
while( 1 ) {
print $array[ $i++ % @array ], "\n";
last if $i > 20;
}
You can also use Tie::Cycle
to use a scalar that always has the next element of the circular array:
常に循環配列の次の要素をもつスカラを使うための、 Tie::Cycle
を使うこともできます:
use Tie::Cycle;
tie my $cycle, 'Tie::Cycle', [ qw( FFFFFF 000000 FFFF00 ) ];
print $cycle; # FFFFFF
print $cycle; # 000000
print $cycle; # FFFF00
The Array::Iterator::Circular
creates an iterator object for circular arrays:
Array::Iterator::Circular
は循環配列のための反復子オブジェクトを 作ります:
use Array::Iterator::Circular;
my $color_iterator = Array::Iterator::Circular->new(
qw(red green blue orange)
);
foreach ( 1 .. 20 ) {
print $color_iterator->next, "\n";
}
配列をランダムにかき混ぜるには?¶
If you either have Perl 5.8.0 or later installed, or if you have Scalar-List-Utils 1.03 or later installed, you can say:
Perl 5.8.0 以降がインストールされているか、Scalar-List-Utils 1.03 以降が インストールされているなら、以下のように出来ます:
use List::Util 'shuffle';
@shuffled = shuffle(@list);
If not, you can use a Fisher-Yates shuffle.
そうでないなら、Fisher-Yates 法が使えます。
sub fisher_yates_shuffle {
my $deck = shift; # $deck is a reference to an array
return unless @$deck; # must not be empty!
my $i = @$deck;
while (--$i) {
my $j = int rand ($i+1);
@$deck[$i,$j] = @$deck[$j,$i];
}
}
# shuffle my mpeg collection
#
my @mpeg = <audio/*/*.mp3>;
fisher_yates_shuffle( \@mpeg ); # randomize @mpeg in place
print @mpeg;
Note that the above implementation shuffles an array in place, unlike the List::Util::shuffle()
which takes a list and returns a new shuffled list.
List::Util::shuffle()
はリストを受け取って、混ぜられた新しいリストを 返しますが、上記の実装は配列そのものを混ぜることに注意してください。
You've probably seen shuffling algorithms that work using splice, randomly picking another element to swap the current element with
splice を使ったシャッフルアルゴリズムを見たことがあるかもしれません。 カレントの要素をランダムに取り出した別の要素と交換します:
srand;
@new = ();
@old = 1 .. 10; # just a demo
while (@old) {
push(@new, splice(@old, rand @old, 1));
}
This is bad because splice is already O(N), and since you do it N times, you just invented a quadratic algorithm; that is, O(N**2). This does not scale, although Perl is so efficient that you probably won't notice this until you have rather largish arrays.
これは splice が O(N) であり、さらにそれを N 回呼んでいるのですから 良くありません。 つまりこれは O(N**2) のアルゴリズムです。 これは大きな配列に使わなければあなたはその効率の悪さに気がつかないでしょう。
配列の各要素に対する処理や、変更を行うには?¶
Use for
/foreach
:
for
/foreach
を使います:
for (@lines) {
s/foo/bar/; # change that word
tr/XZ/ZX/; # swap those letters
}
Here's another; let's compute spherical volumes:
別の方法です; 球の体積を求めます:
for (@volumes = @radii) { # @volumes has changed parts
$_ **= 3;
$_ *= (4/3) * 3.14159; # this will be constant folded
}
which can also be done with map()
which is made to transform one list into another:
リストを他のリストに変換する map()
を使っても行えます:
@volumes = map {$_ ** 3 * (4/3) * 3.14159} @radii;
If you want to do the same thing to modify the values of the hash, you can use the values
function. As of Perl 5.6 the values are not copied, so if you modify $orbit (in this case), you modify the value.
同じことをハッシュの値に対して行いたいのであれば、values
は使えません。 Perl 5.6 以降では値はコピーされないので、(この場合では) $orbit を変更すると、 値を変更することになります。
for $orbit ( values %orbits ) {
($orbit **= 3) *= (4/3) * 3.14159;
}
Prior to perl 5.6 values
returned copies of the values, so older perl code often contains constructions such as @orbits{keys %orbits}
instead of values %orbits
where the hash is to be modified.
perl 5.6 以前では、values
は値のコピーを返すので、古い perl の コードでは、ハッシュを修正しているところで values %orbits
ではなく @orbits{keys %orbits}
と書いていることがよくあります。
ある配列からランダムに要素を選択するには?¶
Use the rand()
function (see "rand" in perlfunc):
rand()
関数を使います("rand" in perlfunc を参照):
$index = rand @array;
$element = $array[$index];
Or, simply:
あるいは、単純に:
my $element = $array[ rand @array ];
N 要素を持つリストの順列(permute)を求めるには?¶
Use the List::Permutor
module on CPAN. If the list is actually an array, try the Algorithm::Permute
module (also on CPAN). It's written in XS code and is very efficient:
CPAN にある List::Permutor
モジュールを使ってください。 リストが実際には配列なら、Algorithm::Permute
モジュール(これも CPAN に あります)を試してください。 これは XS コードで書かれていて、とても効率的です:
use Algorithm::Permute;
my @array = 'a'..'d';
my $p_iterator = Algorithm::Permute->new ( \@array );
while (my @perm = $p_iterator->next) {
print "next permutation: (@perm)\n";
}
For even faster execution, you could do:
より速い実行のために、以下のようにも出来ます:
use Algorithm::Permute;
my @array = 'a'..'d';
Algorithm::Permute::permute {
print "next permutation: (@array)\n";
} @array;
Here's a little program that generates all permutations of all the words on each line of input. The algorithm embodied in the permute()
function is discussed in Volume 4 (still unpublished) of Knuth's The Art of Computer Programming and will work on any list:
以下の小さなプログラムは入力された行にある各単語の順列をすべて生成します。 関数 permute() で使われているアルゴリズムは Knuth の The Art of Computer Programming の Volume 4 (未発行) で 議論されていて、任意のリストで動作するはずです:
#!/usr/bin/perl -n
# Fischer-Krause ordered permutation generator
sub permute (&@) {
my $code = shift;
my @idx = 0..$#_;
while ( $code->(@_[@idx]) ) {
my $p = $#idx;
--$p while $idx[$p-1] > $idx[$p];
my $q = $p or return;
push @idx, reverse splice @idx, $p;
++$q while $idx[$p-1] > $idx[$q];
@idx[$p-1,$q]=@idx[$q,$p-1];
}
}
permute { print "@_\n" } split;
The Algorithm::Loops
module also provides the NextPermute
and NextPermuteNum
functions which efficiently find all unique permutations of an array, even if it contains duplicate values, modifying it in-place: if its elements are in reverse-sorted order then the array is reversed, making it sorted, and it returns false; otherwise the next permutation is returned.
Algorithm::Loops
モジュールも the NextPermute
と NextPermuteNum
の 関数を提供していて、重複した値が含まれていても、その場で変更して、配列の 全てのユニークな順列を探します: もしその要素が逆順にソートされているなら、配列を反転させて、ソートを 行い、偽を返します; さもなければ次の順列を返します。
NextPermute
uses string order and NextPermuteNum
numeric order, so you can enumerate all the permutations of 0..9
like this:
NextPermute
は文字列順を使い、NextPermuteNum
は数値順を使うので、 0..9
の全ての順番を数え上げるには以下のようにします:
use Algorithm::Loops qw(NextPermuteNum);
my @list= 0..9;
do { print "@list\n" } while NextPermuteNum @list;
(なにか)で配列をソートするには?¶
Supply a comparison function to sort() (described in "sort" in perlfunc):
sort() ("sort" in perlfunc に説明があります)のための比較関数を作ります:
@list = sort { $a <=> $b } @list;
The default sort function is cmp, string comparison, which would sort (1, 2, 10)
into (1, 10, 2)
. <=>
, used above, is the numerical comparison operator.
デフォルトのソート関数は文字列比較である cmp で、(1, 2, 10)
を (1, 10, 2)
に並び変えます。 上の例では、数値比較演算子である <=>
を使っています。
If you have a complicated function needed to pull out the part you want to sort on, then don't do it inside the sort function. Pull it out first, because the sort BLOCK can be called many times for the same element. Here's an example of how to pull out the first word after the first number on each item, and then sort those words case-insensitively.
ソートするものの一部を取り出す必要があるような複雑な関数を使うのなら、 ソート関数の内側でそれを使ってはいけません。 最初にその関数で使う部分を取り出します。 なぜなら、sort BLOCK は同じ要素に対して何度も何度も呼び出される 可能性があるからです。 以下の例は、各アイテムの最初の番号の後にある最初の単語を取り出し、 その後でそれらの単語を大小文字を無視してソートします。
@idx = ();
for (@data) {
($item) = /\d+\s*(\S+)/;
push @idx, uc($item);
}
@sorted = @data[ sort { $idx[$a] cmp $idx[$b] } 0 .. $#idx ];
which could also be written this way, using a trick that's come to be known as the Schwartzian Transform:
これはシュワルツ変換と呼ばれるトリックを使って以下のように 書くこともできます:
@sorted = map { $_->[0] }
sort { $a->[1] cmp $b->[1] }
map { [ $_, uc( (/\d+\s*(\S+)/)[0]) ] } @data;
If you need to sort on several fields, the following paradigm is useful.
幾つかのフィールドを使ってソートする必要があるのなら、 以下のやり方が便利でしょう。
@sorted = sort {
field1($a) <=> field1($b) ||
field2($a) cmp field2($b) ||
field3($a) cmp field3($b)
} @data;
This can be conveniently combined with precalculation of keys as given above.
これは先の例にあったキーの precalculation と組み合わせることも できます。
See the sort article in the "Far More Than You Ever Wanted To Know" collection in http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz for more about this approach.
この手法に関する更なる情報については http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz にある "Far More Than You Ever Wanted To Know" コレクションの sort という記事を 参照してください。
See also the question later in perlfaq4 on sorting hashes.
perlfaq4 で後述する、ハッシュのソートに関する質問も参照してください。
ビット配列を扱うには?¶
Use pack()
and unpack()
, or else vec()
and the bitwise operations.
pack()
と unpack()
か、vec()
とビット演算を使います。
For example, you don't have to store individual bits in an array (which would mean that you're wasting a lot of space). To convert an array of bits to a string, use vec()
to set the right bits. This sets $vec
to have bit N set only if $ints[N]
was set:
例えば、それぞれのビットを配列に格納する(これをすると多くのメモリが 無駄になります)必要はありません。 ビットの配列を文字列に変換するには、正しいビットをセットするのに vec()
使います。 これは、$ints[N]
がセットされている場合のみ $vec
の bit N を セットします。
@ints = (...); # array of bits, e.g. ( 1, 0, 0, 1, 1, 0 ... )
$vec = '';
foreach( 0 .. $#ints ) {
vec($vec,$_,1) = 1 if $ints[$_];
}
The string $vec
only takes up as many bits as it needs. For instance, if you had 16 entries in @ints
, $vec
only needs two bytes to store them (not counting the scalar variable overhead).
文字列 $vec
は必要なビット数だけを取ります。 例えば、@ints
に 16 エントリがあるとすると、$vec
はこれを 格納するのに (スカラ変数のオーバーヘッドを除いて) 2 バイトだけを 使います。
Here's how, given a vector in $vec
, you can get those bits into your @ints
array:
次に挙げる例は、$vec
で与えられるベクターのビットを配列 @ints
に 取り出すものです:
sub bitvec_to_list {
my $vec = shift;
my @ints;
# Find null-byte density then select best algorithm
if ($vec =~ tr/\0// / length $vec > 0.95) {
use integer;
my $i;
# This method is faster with mostly null-bytes
while($vec =~ /[^\0]/g ) {
$i = -9 + 8 * pos $vec;
push @ints, $i if vec($vec, ++$i, 1);
push @ints, $i if vec($vec, ++$i, 1);
push @ints, $i if vec($vec, ++$i, 1);
push @ints, $i if vec($vec, ++$i, 1);
push @ints, $i if vec($vec, ++$i, 1);
push @ints, $i if vec($vec, ++$i, 1);
push @ints, $i if vec($vec, ++$i, 1);
push @ints, $i if vec($vec, ++$i, 1);
}
}
else {
# This method is a fast general algorithm
use integer;
my $bits = unpack "b*", $vec;
push @ints, 0 if $bits =~ s/^(\d)// && $1;
push @ints, pos $bits while($bits =~ /1/g);
}
return \@ints;
}
This method gets faster the more sparse the bit vector is. (Courtesy of Tim Bunce and Winfried Koenig.)
この方法はビットベクターが疎であるときにさらに高速になります (Tim Bunce と Winfried Koenig によるものです)。
You can make the while loop a lot shorter with this suggestion from Benjamin Goldberg:
Benjamin Goldberg の提案を使って、while ループをはるかに 短くすることもできます:
while($vec =~ /[^\0]+/g ) {
push @ints, grep vec($vec, $_, 1), $-[0] * 8 .. $+[0] * 8;
}
Or use the CPAN module Bit::Vector
:
または CPAN の Bit::Vector
モジュールを使います:
$vector = Bit::Vector->new($num_of_bits);
$vector->Index_List_Store(@ints);
@ints = $vector->Index_List_Read();
Bit::Vector
provides efficient methods for bit vector, sets of small integers and "big int" math.
Bit::Vector
は、ビットベクタ、小さい整数の就業、「大きな整数」の 計算に関する効果的なメソッドを提供します。
Here's a more extensive illustration using vec():
以下は、vec() を使った広範囲な説明です:
# vec demo
$vector = "\xff\x0f\xef\xfe";
print "Ilya's string \\xff\\x0f\\xef\\xfe represents the number ",
unpack("N", $vector), "\n";
$is_set = vec($vector, 23, 1);
print "Its 23rd bit is ", $is_set ? "set" : "clear", ".\n";
pvec($vector);
set_vec(1,1,1);
set_vec(3,1,1);
set_vec(23,1,1);
set_vec(3,1,3);
set_vec(3,2,3);
set_vec(3,4,3);
set_vec(3,4,7);
set_vec(3,8,3);
set_vec(3,8,7);
set_vec(0,32,17);
set_vec(1,32,17);
sub set_vec {
my ($offset, $width, $value) = @_;
my $vector = '';
vec($vector, $offset, $width) = $value;
print "offset=$offset width=$width value=$value\n";
pvec($vector);
}
sub pvec {
my $vector = shift;
my $bits = unpack("b*", $vector);
my $i = 0;
my $BASE = 8;
print "vector length in bytes: ", length($vector), "\n";
@bytes = unpack("A8" x length($vector), $bits);
print "bits are: @bytes\n\n";
}
なぜ空の配列やハッシュに defined() を使ったときに真が返ってくるのでしょう?¶
The short story is that you should probably only use defined on scalars or functions, not on aggregates (arrays and hashes). See "defined" in perlfunc in the 5.004 release or later of Perl for more detail.
簡単にいえば、スカラや関数に対してのみ defined を使うべきで、 集成体(aggregates, 配列やハッシュ)に対して使うべきではないのです。 詳しくは 5.004 以降の "defined" in perlfunc を参照してください。
データ: ハッシュ(連想配列)¶
ハッシュ全体を処理するには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
There are a couple of ways that you can process an entire hash. You can get a list of keys, then go through each key, or grab a one key-value pair at a time.
ハッシュ全体を処理するには二つの方法があります。 キーのリストを取得してからキー毎に処理するか、一度に一つのキー-値の ペアを取得するかです。
To go through all of the keys, use the keys
function. This extracts all of the keys of the hash and gives them back to you as a list. You can then get the value through the particular key you're processing:
全てのキーを得るには、keys
関数を使います。 ハッシュの全てのキーを展開してリストの形で返します。 それから処理したい特定のキーの値を取得します。
foreach my $key ( keys %hash ) {
my $value = $hash{$key}
...
}
Once you have the list of keys, you can process that list before you process the hash elements. For instance, you can sort the keys so you can process them in lexical order:
キーのリストを取得したら、ハッシュ要素を処理する前にリストを処理できます。 例えば、キーをソートしてレキシカルな順序で処理できます:
foreach my $key ( sort keys %hash ) {
my $value = $hash{$key}
...
}
Or, you might want to only process some of the items. If you only want to deal with the keys that start with text:
, you can select just those using grep
:
あるいは、アイテムの一部に対してのみ処理したいかもしれません。 キーが text:
で始まるキーのみ扱いたいなら、単に grep
を使って 選択できます:
foreach my $key ( grep /^text:/, keys %hash ) {
my $value = $hash{$key}
...
}
If the hash is very large, you might not want to create a long list of keys. To save some memory, you can grab one key-value pair at a time using each()
, which returns a pair you haven't seen yet:
ハッシュがとても大きい場合、キーの長いリストを作りたくないかもしれません。 メモリを節約するために、まだ取得していないキー-値の組を一つ返す each()
を 使って組を取得できます:
while( my( $key, $value ) = each( %hash ) ) {
...
}
The each
operator returns the pairs in apparently random order, so if ordering matters to you, you'll have to stick with the keys
method.
each
演算子は組を一見ランダムな順序で返すので、順序が問題になる場合は、 keys
メソッドを使う必要があります。
The each()
operator can be a bit tricky though. You can't add or delete keys of the hash while you're using it without possibly skipping or re-processing some pairs after Perl internally rehashes all of the elements. Additionally, a hash has only one iterator, so if you use keys
, values
, or each
on the same hash, you can reset the iterator and mess up your processing. See the each
entry in perlfunc for more details.
しかし、each()
演算子は少しトリッキーです。 Perl が内部的に全ての要素を再ハッシュした後にいくつかの組をスキップしたり 再処理したりすることなく、ハッシュの使用中にハッシュのキーを追加したり 削除したりすることは出来ません。 さらに、一つのハッシュは一つのイテレータしか持っていないので、もし同じ ハッシュに対して keys
, values
, each
を使うと、イテレータを リセットしてしまって処理が無茶苦茶になってしまいます。 さらなる詳細については perlfunc の each
エントリを参照してください。
二つのハッシュをマージするには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
Before you decide to merge two hashes, you have to decide what to do if both hashes contain keys that are the same and if you want to leave the original hashes as they were.
二つのハッシュをマージしようと決める前に、もし両方のハッシュに 同じキーがあったときにどうするかと、元のハッシュをそのままに しておくかどうかを決める必要があります。
If you want to preserve the original hashes, copy one hash (%hash1
) to a new hash (%new_hash
), then add the keys from the other hash (%hash2
to the new hash. Checking that the key already exists in %new_hash
gives you a chance to decide what to do with the duplicates:
もし元のハッシュを保存しておきたいなら、一つのハッシュ (%hash1
) を 新しいハッシュ (%new_hash
) にコピーして、それからもう一つのハッシュ (%hash2
) からキーを新しいハッシュに追加します。 キーが既に %new_hash
にある場合、重複をどうするかを決定する 機会が与えられます:
my %new_hash = %hash1; # make a copy; leave %hash1 alone
foreach my $key2 ( keys %hash2 )
{
if( exists $new_hash{$key2} )
{
warn "Key [$key2] is in both hashes!";
# handle the duplicate (perhaps only warning)
...
next;
}
else
{
$new_hash{$key2} = $hash2{$key2};
}
}
If you don't want to create a new hash, you can still use this looping technique; just change the %new_hash
to %hash1
.
新しいハッシュを作りたくない場合は、やはりこのループ技術が使えます; 単に %new_hash
を %hash1
に変更します。
foreach my $key2 ( keys %hash2 )
{
if( exists $hash1{$key2} )
{
warn "Key [$key2] is in both hashes!";
# handle the duplicate (perhaps only warning)
...
next;
}
else
{
$hash1{$key2} = $hash2{$key2};
}
}
If you don't care that one hash overwrites keys and values from the other, you could just use a hash slice to add one hash to another. In this case, values from %hash2
replace values from %hash1
when they have keys in common:
片方のキーと値がもう片方で上書きされても気にしないなら、片方のハッシュから もう片方に追加するために単にハッシュスライスを使えます。 この場合、共通のキーがあった場合は、 %hash1
の値は %hash2
の値で置き換えられます:
@hash1{ keys %hash2 } = values %hash2;
ハッシュに対して反復操作を行っているときにキーの追加や削除をすると何が起きますか?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
The easy answer is "Don't do that!"
簡単な答えは:「そんなことをするな!」
If you iterate through the hash with each(), you can delete the key most recently returned without worrying about it. If you delete or add other keys, the iterator may skip or double up on them since perl may rearrange the hash table. See the entry for each()
in perlfunc.
ハッシュを each() で反復すると、それについて気にすることなく、 最後に返されたキーを削除できます。 他のキーを削除または追加すると、perl はハッシュテーブルを再構成するので、 反復子はキーを読み飛ばしたり重複して読んだりするかもしれません。 perlfunc の each()
のエントリを参照してください。
ハッシュの要素をその値で検索するには?¶
Create a reverse hash:
リバースハッシュを作成します:
%by_value = reverse %by_key;
$key = $by_value{$value};
That's not particularly efficient. It would be more space-efficient to use:
これは特に効率がよいものではありません。 空間を効率よく使うにはこうします:
while (($key, $value) = each %by_key) {
$by_value{$value} = $key;
}
If your hash could have repeated values, the methods above will only find one of the associated keys. This may or may not worry you. If it does worry you, you can always reverse the hash into a hash of arrays instead:
ハッシュに同じ値がある場合には、このメソッドは最初に見つかったキーだけを 見つけだします。 あなたはこれを気にするかも知れませんし、気にしないかもしれません。 もし気にするのなら、いつでもハッシュの代わりに配列のハッシュを 使うことができます:
while (($key, $value) = each %by_key) {
push @{$key_list_by_value{$value}}, $key;
}
ハッシュにどれくらいの要素があるのを知るには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
This is very similar to "How do I process an entire hash?", also in perlfaq4, but a bit simpler in the common cases.
これは perlfaq4 の "How do I process an entire hash?" と とてもよく似ていますが、一般的な場合では少し単純になります。
You can use the keys()
built-in function in scalar context to find out have many entries you have in a hash:
ハッシュにいくつのエントリがあるかを知るために、スカラコンテキストで keys()
組み込み関数を使えます:
my $key_count = keys %hash; # must be scalar context!
If you want to find out how many entries have a defined value, that's a bit different. You have to check each value. A grep
is handy:
定義された値のエントリがいくつあるかを知りたい場合は、少し異なります。 それぞれの値をチェックする必要があります。 grep
が便利です:
my $defined_value_count = grep { defined } values %hash;
You can use that same structure to count the entries any way that you like. If you want the count of the keys with vowels in them, you just test for that instead:
ある特定の条件を持つエントリを数える場合には全て同じ構造が使えます。 もしキーに母音が含まれているエントリを数えたい場合、そのように テストを置き換えるだけです:
my $vowel_count = grep { /[aeiou]/ } keys %hash;
The grep
in scalar context returns the count. If you want the list of matching items, just use it in list context instead:
スカラコンテキストでの grep
は個数を返します。 マッチングしたアイテムのリストが欲しい場合、代わりに単にリストコンテキストで 使います:
my @defined_values = grep { defined } values %hash;
The keys()
function also resets the iterator, which means that you may see strange results if you use this between uses of other hash operators such as each()
.
keys()
関数も反復動作を初期化するので、もしこれを each()
のような 他のハッシュ演算子を使っている間に使うと、おかしな結果になります。
ハッシュを(キーではなく値で)ソートするには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
To sort a hash, start with the keys. In this example, we give the list of keys to the sort function which then compares them ASCIIbetically (which might be affected by your locale settings). The output list has the keys in ASCIIbetical order. Once we have the keys, we can go through them to create a report which lists the keys in ASCIIbetical order.
ハッシュをソートするために、キーから始めます。 この例では、キーのリストをソート関数に渡して、それから ASCII 順で比較します (ロケール設定の影響を受けるかもしれません)。 出力リストは ASCII 順のキーのリストです。 キーを得たら、ASCII 順にキーを並べたレポートを作成します。
my @keys = sort { $a cmp $b } keys %hash;
foreach my $key ( @keys )
{
printf "%-20s %6d\n", $key, $hash{$key};
}
We could get more fancy in the sort()
block though. Instead of comparing the keys, we can compute a value with them and use that value as the comparison.
しかし、sort()
ブロックでもっと面白いことができます。 キーを比較する代わりに、これらの値を計算してその値を比較に使います。
For instance, to make our report order case-insensitive, we use the \L
sequence in a double-quoted string to make everything lowercase. The sort()
block then compares the lowercased values to determine in which order to put the keys.
例えば、大文字小文字を無視した順序のレポートを作るには、全てを小文字に するためにダブルクォートされた文字列の中で \L
シーケンスが使えます。 それから sort()
ブロックがキーを出力する順番を決定するために小文字化された 値を比較します。
my @keys = sort { "\L$a" cmp "\L$b" } keys %hash;
Note: if the computation is expensive or the hash has many elements, you may want to look at the Schwartzian Transform to cache the computation results.
注意: 計算が高くつくものであったり、ハッシュがたくさんの要素を持っている 場合、計算結果をキャッシュするためにシュワルツ変換を使いたいかもしれません。
If we want to sort by the hash value instead, we use the hash key to look it up. We still get out a list of keys, but this time they are ordered by their value.
もし代わりにハッシュの値でソートしたいなら、それを探すためにハッシュキーを 使います。 やはりキーのリストを使いますが、今度はその値でソートします。
my @keys = sort { $hash{$a} <=> $hash{$b} } keys %hash;
From there we can get more complex. If the hash values are the same, we can provide a secondary sort on the hash key.
ここから、より複雑なものにできます。 ハッシュ値が同じ場合は、ハッシュキーによる第二段階のソートを提供できます。
my @keys = sort {
$hash{$a} <=> $hash{$b}
or
"\L$a" cmp "\L$b"
} keys %hash;
私のハッシュを常にソートされた状態にしておくには?¶
You can look into using the DB_File
module and tie()
using the $DB_BTREE
hash bindings as documented in "In Memory Databases" in DB_File. The Tie::IxHash
module from CPAN might also be instructive. Although this does keep your hash sorted, you might not like the slowdown you suffer from the tie interface. Are you sure you need to do this? :)
"In Memory Databases" in DB_File にあるように、DB_File
モジュールと tie()
を使った、$DB_BTREE ハッシュ束縛を使うことができます。 CPAN の Tie::IxHash
モジュールも有益かもしれません。 これによりハッシュはソートされた状態のままになりますが、tie インターフェースによって被る速度低下を気に入らないかもしれません。 あなたは本当にこれが必要ですか? :)
ハッシュに対する "delete" と "undef"との間の違いは?¶
Hashes contain pairs of scalars: the first is the key, the second is the value. The key will be coerced to a string, although the value can be any kind of scalar: string, number, or reference. If a key $key
is present in %hash, exists($hash{$key})
will return true. The value for a given key can be undef
, in which case $hash{$key}
will be undef
while exists $hash{$key}
will return true. This corresponds to ($key
, undef
) being in the hash.
ハッシュはスカラのペアからなります: 最初のスカラがキーで、 二番目のスカラが値です。 キーは文字列、数値、リファレンスのいずれの種類のスカラであっても 強制的に文字列にされます。 %hash の中に $key
というキーが既にあれば、exists($hash{$key})
は 真を返します。 与えられたキーに対する値は undef
とすることができます。 これは $hash{$key}
を undef
にして、exists $hash{$key}
が真を 返すという状態です。 これは ($key
, undef
)がハッシュに存在しているということを示しています。
Pictures help... Here's the %hash
table:
図が助けになるでしょう。 以下は %hash
のテーブルです:
keys values
+------+------+
| a | 3 |
| x | 7 |
| d | 0 |
| e | 2 |
+------+------+
And these conditions hold
そしてこれらが保持している状態はこうです:
$hash{'a'} is true
$hash{'d'} is false
defined $hash{'d'} is true
defined $hash{'a'} is true
exists $hash{'a'} is true (Perl 5 only)
grep ($_ eq 'a', keys %hash) is true
If you now say
ここで
undef $hash{'a'}
your table now reads:
とすると、テーブルはこうなります:
keys values
+------+------+
| a | undef|
| x | 7 |
| d | 0 |
| e | 2 |
+------+------+
and these conditions now hold; changes in caps:
そしてその状態は以下のようになります。 大文字になっているのが変わった場所です:
$hash{'a'} is FALSE
$hash{'d'} is false
defined $hash{'d'} is true
defined $hash{'a'} is FALSE
exists $hash{'a'} is true (Perl 5 only)
grep ($_ eq 'a', keys %hash) is true
Notice the last two: you have an undef value, but a defined key!
最後の二つに注目してください: あなたは undef 値を保持していますが、 キーは define されているのです!
Now, consider this:
さて、こんどは以下の例を考えてみましょう:
delete $hash{'a'}
your table now reads:
とすると、テーブルはこうなります:
keys values
+------+------+
| x | 7 |
| d | 0 |
| e | 2 |
+------+------+
and these conditions now hold; changes in caps:
そしてその状態は以下のようになります。 大文字になっているのが変わった場所です:
$hash{'a'} is false
$hash{'d'} is false
defined $hash{'d'} is true
defined $hash{'a'} is false
exists $hash{'a'} is FALSE (Perl 5 only)
grep ($_ eq 'a', keys %hash) is FALSE
See, the whole entry is gone!
ほら、エントリが丸ごとなくなっていまいました!
なぜわたしの tie されたハッシュは defined と exists を区別しないのでしょうか?¶
This depends on the tied hash's implementation of EXISTS(). For example, there isn't the concept of undef with hashes that are tied to DBM* files. It also means that exists() and defined() do the same thing with a DBM* file, and what they end up doing is not what they do with ordinary hashes.
これは tie されたハッシュの EXISTS() の実装に依存します。 たとえば、DBM* ファイルに tie されたハッシュには undef という考え方はありません。 これはまた DBM* ファイルにとっては exists() と defined() とは同じことであり、 そういったものに対して行っていることは 通常のハッシュに対して行っていることとは違うのだということなのです。
each() 操作の途中でリセットしてしまうには?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
You can use the keys
or values
functions to reset each
. To simply reset the iterator used by each
without doing anything else, use one of them in void context:
each
をリセットするために keys
関数か values
関数が使えます。 他に何もせずに単に each
で使われているイテレータをリセットするには、 これらの一つを無効コンテキストで使います:
keys %hash; # resets iterator, nothing else.
values %hash; # resets iterator, nothing else.
See the documentation for each
in perlfunc.
perlfunc にある each
の説明を参照してください。
二つのハッシュからユニークなキーを取りだすには?¶
First you extract the keys from the hashes into lists, then solve the "removing duplicates" problem described above. For example:
まず最初にハッシュからキーを取りだして、それをリストに格納します。 そして、先に説明した「重複の削除」問題の解決を行います。例:
%seen = ();
for $element (keys(%foo), keys(%bar)) {
$seen{$element}++;
}
@uniq = keys %seen;
Or more succinctly:
あるいはもっと簡潔に:
@uniq = keys %{{%foo,%bar}};
Or if you really want to save space:
もし本当にメモリ空間を節約したいのなら:
%seen = ();
while (defined ($key = each %foo)) {
$seen{$key}++;
}
while (defined ($key = each %bar)) {
$seen{$key}++;
}
@uniq = keys %seen;
DBM ファイルに多次元配列を格納するには?¶
Either stringify the structure yourself (no fun), or else get the MLDBM (which uses Data::Dumper) module from CPAN and layer it on top of either DB_File or GDBM_File. You might also try DBM::Deep, but it can be a bit slow.
自分自身で構造を文字列化する(うれしくないですね)か、MLDBM モジュール (Data::Dumper を使います)を CPAN から取ってきて、DB_File か GDBM_File のいずれかのトップ層にします。 DBM::Deep を試すこともできますが、少し遅いかもしれません。
わたしのハッシュが格納した順番を覚えておくようにするには?¶
Use the Tie::IxHash
from CPAN.
CPAN にある Tie::IxHash
を使います。
use Tie::IxHash;
tie my %myhash, 'Tie::IxHash';
for (my $i=0; $i<20; $i++) {
$myhash{$i} = 2*$i;
}
my @keys = keys %myhash;
# @keys = (0,1,2,3,...)
なぜあるハッシュの未定義要素をサブルーチンに渡すとそれを作成するのでしょうか?¶
(contributed by brian d foy)
(brian d foy によって寄贈されました)
Are you using a really old version of Perl?
本当に古いバージョンの Perl を使っているのですか?
Normally, accessing a hash key's value for a nonexistent key will not create the key.
普通は、存在しないキーの値にアクセスしてもキーは作成 されません。
my %hash = ();
my $value = $hash{ 'foo' };
print "This won't print\n" if exists $hash{ 'foo' };
Passing $hash{ 'foo' }
to a subroutine used to be a special case, though. Since you could assign directly to $_[0]
, Perl had to be ready to make that assignment so it created the hash key ahead of time:
しかし、$hash{ 'foo' }
をサブルーチンに渡す場合は特別扱いでした。 $_[0]
に直接代入できるので、Perl はそのような代入に備える必要があり、 そのためハッシュキーを予め作成していました:
my_sub( $hash{ 'foo' } );
print "This will print before 5.004\n" if exists $hash{ 'foo' };
sub my_sub {
# $_[0] = 'bar'; # create hash key in case you do this
1;
}
Since Perl 5.004, however, this situation is a special case and Perl creates the hash key only when you make the assignment:
しかし、Perl 5.004 からは、この状況は特別扱いで、Perl は代入が 行われた場合にのみハッシュキーを作成します:
my_sub( $hash{ 'foo' } );
print "This will print, even after 5.004\n" if exists $hash{ 'foo' };
sub my_sub {
$_[0] = 'bar';
}
However, if you want the old behavior (and think carefully about that because it's a weird side effect), you can pass a hash slice instead. Perl 5.004 didn't make this a special case:
しかし、昔の振る舞いにしたい(そしてこれにより奇妙な副作用が起こることについて 慎重に考えた)なら、代わりにハッシュスライスを渡せます。 Perl 5.004 はこれを特別扱いしませんでした:
my_sub( @hash{ qw/foo/ } );
C の構造体/C++ のクラスのハッシュ、配列のハッシュ、配列と等価なものを Perl で作成するには?¶
Usually a hash ref, perhaps like this:
通常はハッシュのリファレンスを使います。 多分以下のようになるでしょう:
$record = {
NAME => "Jason",
EMPNO => 132,
TITLE => "deputy peon",
AGE => 23,
SALARY => 37_000,
PALS => [ "Norbert", "Rhys", "Phineas"],
};
References are documented in perlref and perlreftut. Examples of complex data structures are given in perldsc and perllol. Examples of structures and object-oriented classes are in perltoot.
リファレンスは perlref と perlreftut に説明があります。 複雑なデータ構造の例が perldesc と perllol にあります。 構造体とオブジェクト指向クラスの例が perltoot にあります。
ハッシュのキーとしてリファレンスを使うには?¶
(contributed by brian d foy and Ben Morrow)
(brian d foy と Ben Morrow によって寄贈されました)
Hash keys are strings, so you can't really use a reference as the key. When you try to do that, perl turns the reference into its stringified form (for instance, HASH(0xDEADBEEF)
). From there you can't get back the reference from the stringified form, at least without doing some extra work on your own.
ハッシュキーは文字列なので、実際にリファレンスをキーとして使うことは できません。 もしそうしようとすると、perl はリファレンスを(例えば HASH(0xDEADBEEF)
の 形に)文字列化します。 少なくとも自分自身で追加の作業をしない限り、文字列化された形から リファレンスを得ることはできません。
Remember that the entry in the hash will still be there even if the referenced variable goes out of scope, and that it is entirely possible for Perl to subsequently allocate a different variable at the same address. This will mean a new variable might accidentally be associated with the value for an old.
ハッシュのエントリはリファレンスされた値がスコープ外に出ても 存在していて、その後 Perl が同じアドレスに別の変数を割り当てる可能性が あることを忘れないでください。 これは、新しい変数が偶然古い変数の値と関連づけられるかもしれないことを 意味します。
If you have Perl 5.10 or later, and you just want to store a value against the reference for lookup later, you can use the core Hash::Util::Fieldhash module. This will also handle renaming the keys if you use multiple threads (which causes all variables to be reallocated at new addresses, changing their stringification), and garbage-collecting the entries when the referenced variable goes out of scope.
Perl 5.10 以降を使っていて、単に後で参照するためにリファレンスで 値を保管したいだけなら、 コアの Hash::Util::Fieldhash モジュールが使えます。 これはまた、もしマルチスレッドを使っている(つまり全ての変数は 新しいアドレスに再割り当てされ、文字列化した結果が変わる)場合は キーの名前の変更を扱い、リファレンスされた変数がスコープ外に 出た場合はガベージコレクションを行います。
If you actually need to be able to get a real reference back from each hash entry, you can use the Tie::RefHash module, which does the required work for you.
本当にそれぞれのハッシュエントリから実際のリファレンスを得る必要があるのなら、 それに必要な作業を行う Tie::RefHash モジュールが使えます。
複数レベルハッシュにキーがあるかどうかをチェックするには?¶
(contributed by brian d foy)
(contributed by brian d foy)
(brian d foy によって寄贈されました)
The trick to this problem is avoiding accidental autovivification. If you want to check three keys deep, you might na誰vely try this:
このトリックは偶発的な自動有効化を防ぎます。 3 レベルの深さのキーをチェックするとき、単純に以下のように 試すかもしれません:
my %hash;
if( exists $hash{key1}{key2}{key3} ) {
...;
}
Even though you started with a completely empty hash, after that call to exists
you've created the structure you needed to check for key3
:
完全にからのハッシュから始めたときでさえ、exists
の呼び出し後 key3
のチェックに必要な構造が作成されます:
%hash = (
'key1' => {
'key2' => {}
}
);
That's autovivification. You can get around this in a few ways. The easiest way is to just turn it off. The lexical autovivification
pragma is available on CPAN. Now you don't add to the hash:
これが自動有効化です。 これはいくつかの方法で回避できます。 最も簡単な方法は単にこれをオフにすることです。 レキシカルな autovivification
プラグマは CPAN で利用可能です。 これでハッシュを追加しません:
{
no autovivification;
my %hash;
if( exists $hash{key1}{key2}{key3} ) {
...;
}
}
The Data::Diver
module on CPAN can do it for you too. Its Dive
subroutine can tell you not only if the keys exist but also get the value:
CPAN にある Data::Diver
モジュールもあなたのために動作します。 これの Dive
サブルーチンはキーがあるかだけでなく値も取得します:
use Data::Diver qw(Dive);
my @exists = Dive( \%hash, qw(key1 key2 key3) );
if( ! @exists ) {
...; # keys do not exist
}
elsif( ! defined $exists[0] ) {
...; # keys exist but value is undef
}
You can easily do this yourself too by checking each level of the hash before you move onto the next level. This is essentially what Data::Diver
does for you:
次のレベルに移動する前にそれぞれのレベルのハッシュがあるかどうかを チェックすることで、これを自分自身で行うことも簡単にできます。 これは本質的には Data::Diver
がしてくれることです:
if( check_hash( \%hash, qw(key1 key2 key3) ) ) {
...;
}
sub check_hash {
my( $hash, @keys ) = @_;
return unless @keys;
foreach my $key ( @keys ) {
return unless eval { exists $hash->{$key} };
$hash = $hash->{$key};
}
return 1;
}
データ:その他¶
バイナリデータを正しく扱うには?¶
Perl is binary-clean, so it can handle binary data just fine. On Windows or DOS, however, you have to use binmode
for binary files to avoid conversions for line endings. In general, you should use binmode
any time you want to work with binary data.
Perl はバイナリクリーンですから、バイナリデータをうまく扱えます。 しかし、 Windows や DOS では、バイナリファイルに対して行末の変換を避けるために、 binmode
を使う必要があります。 一般的には、バイナリデータを扱いたいときはいつでも binmode
を 使うべきです。
Also see "binmode" in perlfunc or perlopentut.
"binmode" in perlfunc と perlopentut も参照してください。
If you're concerned about 8-bit textual data then see perllocale. If you want to deal with multibyte characters, however, there are some gotchas. See the section on Regular Expressions.
もし 8 ビットテキストデータについて考えているのであれば、perllocale を 参照してください。 ただしマルチバイトキャラクターを扱いたいと考えているなら、幾つかの 罠(gotchas)があります。 正規表現のセクションを参照してください。
あるスカラ値が数値/整数/浮動小数点数かどうかを決定するには?¶
Assuming that you don't care about IEEE notations like "NaN" or "Infinity", you probably just want to use a regular expression:
"NaN" や "Infinity" のような IEEE 表記については気にしないと仮定すると、 正規表現を使って行うことができます:
use 5.010;
given( $number ) {
when( /\D/ )
{ say "\thas nondigits"; continue }
when( /^\d+\z/ )
{ say "\tis a whole number"; continue }
when( /^-?\d+\z/ )
{ say "\tis an integer"; continue }
when( /^[+-]?\d+\z/ )
{ say "\tis a +/- integer"; continue }
when( /^-?(?:\d+\.?|\.\d)\d*\z/ )
{ say "\tis a real number"; continue }
when( /^[+-]?(?=\.?\d)\d*\.?\d*(?:e[+-]?\d+)?\z/i)
{ say "\tis a C float" }
}
There are also some commonly used modules for the task. Scalar::Util (distributed with 5.8) provides access to perl's internal function looks_like_number
for determining whether a variable looks like a number. Data::Types exports functions that validate data types using both the above and other regular expressions. Thirdly, there is Regexp::Common
which has regular expressions to match various types of numbers. Those three modules are available from the CPAN.
この作業のためによく使われるいくつかのモジュールがあります。 Scalar::Util (5.8 と共に配布されています) は、変数が数値に見えるか どうかを決定するために perl の内部関数 looks_like_number
へのアクセスを 提供します。 Data::Types は上記のものとその他の正規表現の両方を使ってデータ型の バリデートを行う関数をエクスポートします。 3 つめとして、Regexp::Common
には様々な種類の数値にマッチングする 正規表現があります。 これら 3 つのモジュールは CPAN にあります。
If you're on a POSIX system, Perl supports the POSIX::strtod
function for converting strings to doubles (and also POSIX::strtol
for longs). Its semantics are somewhat cumbersome, so here's a getnum
wrapper function for more convenient access. This function takes a string and returns the number it found, or undef
for input that isn't a C float. The is_numeric
function is a front end to getnum
if you just want to say, "Is this a float?"
POSIXシステムを使っているのなら、Perl は文字列を double に変換する POSIX::strtod
関数 (および long のための POSIX::strtol
関数) に 対応しています。 そのセマンティックは扱いにくいもので、もっと便利にアクセスするための getnum
関数を以下に例示します。 この関数は文字列を引数に取り、その文字列中で見つかった数字列に対応する 数値を返し、入力がCの小数点表記にあわないものであれば undef
を返します。 is_numeric
関数は“これは数値か?”ということを知りたい場合に getnum
のフロントエンドとなります。
sub getnum {
use POSIX qw(strtod);
my $str = shift;
$str =~ s/^\s+//;
$str =~ s/\s+$//;
$! = 0;
my($num, $unparsed) = strtod($str);
if (($str eq '') || ($unparsed != 0) || $!) {
return undef;
}
else {
return $num;
}
}
sub is_numeric { defined getnum($_[0]) }
Or you could check out the String::Scanf module on the CPAN instead.
あるいは、CPAN にある String::Scanf モジュールをチェックしてみてください。
プログラムの呼び出しの間に、データ構造を永続的に保持するには?¶
For some specific applications, you can use one of the DBM modules. See AnyDBM_File. More generically, you should consult the FreezeThaw
or Storable
modules from CPAN. Starting from Perl 5.8 Storable
is part of the standard distribution. Here's one example using Storable
's store
and retrieve
functions:
一部の特定のアプリケーションでは、DBM モジュールの一つを使うことができます。 AnyDBM_File を参照してください。 より一般的には、CPAN にある FreezeThaw
, Storable
といった モジュールをあたってみるべきでしょう。 Perl 5.8 から、Storable
は標準配布の一部となりました。 以下に Storable
の store
と retrieve
を使った例を挙げます:
use Storable;
store(\%hash, "filename");
# later on...
$href = retrieve("filename"); # by ref
%hash = %{ retrieve("filename") }; # direct to hash
再帰的なデータ構造を出力したりコピーするには?¶
The Data::Dumper
module on CPAN (or the 5.005 release of Perl) is great for printing out data structures. The Storable
module on CPAN (or the 5.8 release of Perl), provides a function called dclone
that recursively copies its argument.
CPAN にある Data::Dumper
モジュール(5.005 以降では Perl のリリースに 含まれています)はデータ構造を出力するのに向いています。 CPAN にある Storable
モジュール(5.8 以降では Perl のリリースに 含まれています)はその引数を再帰的にコピーする dclone
という関数を提供しています。
use Storable qw(dclone);
$r2 = dclone($r1);
Where $r1
can be a reference to any kind of data structure you'd like. It will be deeply copied. Because dclone
takes and returns references, you'd have to add extra punctuation if you had a hash of arrays that you wanted to copy.
ここで $r1
にはあなたの望むデータ構造のリファレンスを置くことができます。 これは深くコピー(deeply copied)されます。 dclone
はリファレンスを取り リファレンスを返すので、コピーしたいものが配列のハッシュであったりした 場合には余計なpunctuationが必要となるでしょう。
%newhash = %{ dclone(\%oldhash) };
すべてのクラス/オブジェクトのためのメソッドを定義するには?¶
(contributed by Ben Morrow)
(Ben Morrow によって寄贈されました)
You can use the UNIVERSAL
class (see UNIVERSAL). However, please be very careful to consider the consequences of doing this: adding methods to every object is very likely to have unintended consequences. If possible, it would be better to have all your object inherit from some common base class, or to use an object system like Moose that supports roles.
UNIVERSAL
クラス (UNIVERSAL) を参照してください)が使えます。 しかし、これを行うことによる結果の考慮についてはとても注意深く行ってください: 全てのオブジェクトにメソッドを追加すると、想定外の結果になる可能性が とても高いです。 可能なら、あなたの作る全てのオブジェクトを共通の基底クラスから 継承するようにするか、ロールに対応している Moose のような オブジェクトシステムを使う方が良いです。
クレジットカードのチェックサムを検査するには?¶
Get the Business::CreditCard
module from CPAN.
CPAN から Business::CreditCard
モジュールを入手してください。
XSプログラムのために倍精度実数や単精度実数の配列を pack するには?¶
The arrays.h/arrays.c code in the PGPLOT
module on CPAN does just this. If you're doing a lot of float or double processing, consider using the PDL
module from CPAN instead--it makes number-crunching easy.
CPAN にある PGPLOT
モジュールにある arrays.h/arrays.c というものが それをします。 倍精度実数や単精度実数を大量に扱うのであれば、CPAN にある PDL
モジュールを使うことを考えてみるとよいでしょう。 これは number-crunching を簡単にしてくれます。
See http://search.cpan.org/dist/PGPLOT for the code.
コードについては http://search.cpan.org/dist/PGPLOT を参照してください。
AUTHOR AND COPYRIGHT¶
Copyright (c) 1997-2010 Tom Christiansen, Nathan Torkington, and other authors as noted. All rights reserved.
This documentation is free; you can redistribute it and/or modify it under the same terms as Perl itself.
Irrespective of its distribution, all code examples in this file are hereby placed into the public domain. You are permitted and encouraged to use this code in your own programs for fun or for profit as you see fit. A simple comment in the code giving credit would be courteous but is not required.