6

これを行うためのより良い方法を必ずしも探しているわけではありません。出力の説明をいただければ幸いです。最近、シニア プログラマーから、コードが 1 つのインスタンスしか機能しないのはなぜかと尋ねられました。私が見つけたのは、それが他のすべての出来事で機能したということでした. これが私の例です:

#!/usr/bin/perl -w
use strict;

my @list_env_vars = (
    '$SERVER',
    '$SERVER',
    '$SERVER',
    '$SERVER',
    '$SERVER',
    '$SERVER',
);

foreach (@list_env_vars){
    print "$_ = ".glob()."\n";
}

perl 5.004 の出力:

$SERVER = UNIX_SERVER
$SERVER =
$SERVER = UNIX_SERVER
$SERVER =
$SERVER = UNIX_SERVER
$SERVER =

または perl 5.10 の出力:

$SITE = $SITE
Use of uninitialized value in concatenation (.) or string at glob_test.pl line 14.
$SITE =
$SITE = $SITE
Use of uninitialized value in concatenation (.) or string at glob_test.pl line 14.
$SITE =
$SITE = $SITE
Use of uninitialized value in concatenation (.) or string at glob_test.pl line 14.
$SITE =

私は個人的にこの方法で glob() を使用したことがないので、彼に答える準備ができていませんでした。私はperldoc globのドキュメントを読み、そのページのFile::Globリンクをたどりましたが、出力を説明するものを見つけることができませんでした。どんな助けでも大歓迎です。

4

3 に答える 3

13

globスカラーコンテキストでは:

スカラー コンテキストでは、glob はそのようなファイル名展開を繰り返し処理し、リストが使い果たされると undef を返します。

foreach (@list_env_vars){
    print "$_ = ".glob()."\n";
}

glob()本当にありますglob($_)。すべての反復に$_は、文字列が含まれます$SERVER。環境変数が変更されないことを考えると$SERVER、同じ文字列に展開されます。初回は、この文字列が返されます。次に、リストが使い果たされたので、undef返されます。3 回目は、最初からやり直します。...

明確化:globのイテレータをリセットする方法がないため、2 番目の呼び出しの引数が最初の呼び出しの引数と同じであってもかまいません。

次の例を使用すると、これをより明確に確認できます (現在のディレクトリには、ファイル '1.a'、1.b'、'2.a'、および '2.b' が含まれています)。

#!/usr/bin/perl -w
use strict;

my @patterns = (
    '*.a',
    '*.b',
);

for my $v ( @patterns ) {
    print "$v = ", scalar glob($v), "\n";
}

出力:

C:\Temp> d
*.a = 1.a
*.b = 2.a

%ENVハッシュを介して環境変数にアクセスすることをお勧めします。

my @list_env_vars = ($ENV{SERVER}) x 6;

また

my @list_env_vars = @ENV{qw(HOME TEMP SERVER)};
于 2009-08-13T21:39:04.933 に答える
4

ちなみに、5.004 では変数展開が行われ、5.10 ではリテラル文字列が返されるのは、古い perl ではglob()、副作用として変数展開が実行されるのと同じように、システム シェルによって実行されたためです。perl 5.6 以降、シェルなしで作業自体を行うモジュールをglob()使用し、File::Glob環境変数を展開しません (これは glob が意図したものではありませんでした)。%ENV環境に到達するための適切な方法です。

于 2009-08-14T21:50:40.240 に答える
0

古い振る舞いについてのメモ、あなたの便宜のためにwikiしました(そして私がマークアップの全範囲を持ち、500文字の制限がないように):

glob5.6で変更されたという事実は、ドキュメント( 、、<*globbything*>)で言及されていますが、それがどのように機能していたかについての唯一の実際の情報源は、5.6より前のバージョンです。5.005の関連ビットは次のとおりです。perl56deltaperlop-f globperlop

例:

while (<*.c>) {
    chmod 0644, $_;
}

と同等です

open(FOO, "echo *.c | tr -s ' \t\r\f' '\\012\\012\\012\\012'|");
while (<FOO>) {
    chop;
    chmod 0644, $_;
}

実際、現在はそのように実装されています。(つまり、マシンにcsh(1)がない限り、スペースが含まれるファイル名では機能しません。)

ええ、それはかなり邪悪なものです。とにかく、そのような古いperldocsを参照したい場合は、search.cpan.orgにアクセスし、perlディストリビューションをプルアップし、プルダウンリストを使用して古いバージョンを選択してから、必要なドキュメントをクリックしてください。perlそれ自体は、CPANから「整理」されることは実際にはありません。現在、5.004以降のすべてがBackPanを押すことなく利用できます。

于 2009-08-22T06:59:25.643 に答える