2011-12-27 10 views
1

入力ファイルを処理する次のセグメントを含むPerlプログラムを勉強しています。 s/^\s+//;は何のために使われているのですか?さらに、 '|'と '||' open(FILE, "cat $fileName |") || die "could not open file";入力ファイルを処理するコードスニペットの問題

open(FILE, "cat $fileName |") || die "could not open file"; 
while (<FILE>) 
{ 
    s/^\s+//; 
    my @line = split; 
    if ($line[0]!~ /\:/) {$mark=0} 
    my $var = $line[$mark]; 
     ## some other code 
} 
+0

このコードはかなり奇妙です...最初のs/^ \ s + //;まったく何もしていないように見えます。実際、私はそれがエラーを投げると思うでしょう... || ORを表す。と|私は(私が間違っている可能性があるので、iveがperlを使用しているのでしばらくしていたと思う)とは単に開かれているファイルを解読することを意味します。私は素早くgoogle検索を行った。http://www.rocketaware.com/perl/perlfunc/open.htm – Justin

+1

@Justin: 's ///'はデフォルトの引数( '$ _')で動作しているので引数なしの 'split'呼び出しは同じことをしており、while()は' $ _'に代入します。 –

+0

また、 ":"は正規表現では特別なものではないので、 "\" – runrig

答えて

0

開発者がデフォルト変数$_を使用しているという混乱の一部があります。関数内で変数の名前を指定しないと、Perlの多くのコマンド(約1/3はコマンド)が$_になります。例えば、これらは構文的に同一である。両方の場合において

my $uppercase_name = uc($_); 
my $uppercase_name = uc; 

uc関数は大文字で$_変数の文字列を印刷します。実際には、print文でも変数$_が使用されます。ここでも、これらは両方とも同じです。

print $_; 
print; 

それがプログラムに明確さを追加しないと、それはより速くプログラムを作成していないため、より新しいPerlスクリプトで、デフォルトの変数を使用するようにひんしゅくを買うです。私は、欠落した$_変数を表示するために使用したのと同じコードスニペットを書き直しました。 while文が$_変数に読み込む行の値を入れていることと代替コマンド(s/^\s+//)も$_上で動作していることを

open(FILE, "cat $fileName |") || die "could not open file"; 
while ($_ = <FILE>) 
{ 
    $_ =~ s/^\s+//; 
    my @line = split $_; 
    if ($line[0] !~ /\:/) { 
     $mark = 0; 
    } 
    my $var = $line[$mark]; 
     ## some other code 
} 

お知らせ:それは理解し、コードが簡単になるかもしれません変数。私はあなたのためのコードを明確にすることを願っています。ご質問のために今

_ [W]帽子ん '|'と '||'立つ?

||このまたはそのを行うのようにまたはを意味します。実際には、またはは、if文と考えることができます。

if (not open(FILE, "cat $fileName |")) { 
    die "could not open file"; 
} 

オープン文がdie文を実行し、失敗した場合、すなわち。開いているステートメントでファイルを開くことができた場合は、dieステートメントを実行しないでください。 Perlで

、あなたは今、このようなケースではorの代わり||参照:

open(FILE, "cat $fileName |") or die "could not open file"; 

意味がもう少し明らかになりた:ファイルを開く、またはプログラムを強制終了します。

ファイル名の末尾にある単一のパイプ(|)は、openステートメント(cat $filename)でコマンドを実行し、このコマンドの出力から読み取ることを意味します。今

open (COMMAND, "java -jar foo.war|") or die "Can't execute 'java -jar foo.war'"; 

、私はコマンドjava -jar foo.warを実行しているし、私のPerlスクリプトで、その出力を使用しています。このようなものを想像してみてください。

あなたはあまりにも周りにこれに他の方法を行うことができます。私は今、コマンドmail $recipientを開き、print文でそれを書いている

open (MAIL, "|mail $recipient") or die "Can't mail $recipient"; 
print MAIL "Dear $recipient\n\n"; 
print MAIL "I hope everything is well.\n"; 
print MAIL "Sincerely,\n\nDavid"; 
close MAIL; 

。この場合、私は$recipientに簡単なメッセージで電子メールを送ります。

私はs/^ \ s + //とは分かりません。のために使用される?元のプログラムで

、それは単独行にあった:

s/^\s+//; 

私はそれを少し明確に役立つはず変数を逃すを追加しました:

$_ =~ s/^\s+//; 

これはPerlの代替コマンドです。 $_という変数を使用し、正規表現^\s+を何も入力しません。正規表現の内容がわからない場合は、対象のPerldoc tutorialをご覧ください。基本的には、空白、タブ、および他の形式の空白が行の先頭から削除されています。

2

にあなたはperlfuncに様々な機能のドキュメントを読むことができるために立っています。

このコードでは、単にファイルを開くのではなく、catからの配管のほんのわずかな方法で、読み取り用のファイルを開きます。 |は、シェルコマンドcatがopenコマンドにパイプされ、ファイルハンドルが出力から読み取られることを意味します。

||は単純またはです。パイプを開き、失敗した場合はプログラムが終了します。

while(<FILE>)は、入力のすべての行を読み込み、各行を$_に割り当てます。その行は、以下の置換と分割に暗黙的に使用されます。私。 s/^\s+//$_ =~ s/^\s+//に等しく、splitは​​に等しい。

s/^\s+// 

先頭の空白を削除します。分割は空白の各行を分割し、要素は配列@lineに格納されます。

空白で暗黙の分割を使用するため、先頭の空白をs/^\s+//で取り除くことは、自動的に行われるため、実際には必要ありません。

最初の要素はコロン:が含まれていない場合、$markは、そうでなければ0に設定され、それが設定されていない場合、それはループ内で定義されていないので、おそらく、以前の反復からの値を使用します。最後に、$varは、要素番号$markとして初期化されます。0またはそれ以外の値です。

ETA:なく潜行おっととおり$markが定義されていない場合、すなわち、それはコロンが含まれていないundefを警告、0に変換されるので、その後、$varは依然として、$line[0]割り当てられます。 use warningsが有効でない場合、このエラーは無音であり、したがって潜在的です。

このコードはperlをあまり知らない人が書いているようですが、使用するのはあまり安全ではないかもしれません。

+0

これは旧式のPerlです.90年代後半からです。 –

+1

もちろん、古い学校のperlでも普通の方法でファイルを開くことができます。 – TLP

+1

'cat'を使う代わりに' cat'ですか?はい;昔の学校のPerlでも読書のために直接ファイルを開くことができ、[UUOC](http://catb.org/jargon/html/U/UUOC.html)は無意味です。あなたは、そのようなものが単純化されているかどうかは決して確かではありません(少なくとも、私は)。 (私はそれがパイプ入力だったと指摘しましたが、コードを最初に読んだときはUUOCであることに気付かなかった) –

2

置換のトリムは、行頭に(^)に表示されるwhitespaceをトリムし、空白以外の文字は先頭にします。

open... || die ...|| operatorは、優先順位がまたはです。 openが失敗すると、dieが実行されます。

open(FILE, "cat $fileName |")は、外部プロセスの無駄です。入力用のファイルを読み取るには、単純に実行します。orがしっかりと結合しないのでopenコールのための

open FILE, '<', $filename or die qq{Could not open "$filename" for reading: $!}; 

括弧はオプションです。

字句ファイルを使用することも良いですがハンドル:

open my $fh, '<' $filename or die qq{Could not open "$filename" for reading: $!}; 

このファイルハンドルは唯一、それが宣言された範囲内で住んでいるレキシカル変数に割り当てられています。プログラムフローがこのスコープを終了すると、ファイルは自動的に閉じます。

+3

実際、 '||'は(もっと新しい) 'または'の優先順位の高いバージョンです。 '||'が使われているときの混乱を避けるために、カッコで囲んだ 'open'の関数呼び出し表記が必要です。コードは2つの引数をとる 'open'形式を使い、字句ファイルハンドルを使用しないでかなり古くなっています。 'close FILE'も周囲に潜んでいるはずです。 –

+0

また、グローバルファイルハンドルを使用しないことを検討してください。 「[古い方法でファイルを開かないでください](http://szabgab.com/open-files-in-the-old-way.html)」を参照してください。 – asjo

+0

@jonathanLeffler:感謝と訂正---逆さまに考えて:-) – JRFerguson

関連する問題