英語フランス語スペイン語

OnWorksファビコン

perlfaq5-クラウドでのオンライン

Ubuntu Online、Fedora Online、Windows Onlineエミュレーター、またはMACOSオンラインエミュレーターを介してOnWorks無料ホスティングプロバイダーでperlfaq5を実行します

これは、Ubuntu Online、Fedora Online、Windowsオンラインエミュレーター、MACOSオンラインエミュレーターなどの複数の無料オンラインワークステーションの5つを使用してOnWorks無料ホスティングプロバイダーで実行できるコマンドperlfaqXNUMXです。

プログラム:

NAME


perlfaq5 - ファイルとフォーマット

VERSION


バージョン5.021009

DESCRIPTION


このセクションでは、I/O と「f」の問題、つまりファイルハンドル、フラッシュ、フォーマット、および
フッター。

認定条件 do I フラッシュ/バッファ解除 an 出力 ファイルハンドル? なぜ しなければなりません I do この?
(ブライアン・ド・フォイによる寄稿)

Mark Jason Dominus の「Suffering From Buffering」を次のサイトで読んでみてはいかがでしょうか。
<http://perl.plover.com/FAQs/Buffering.html>。

Perl は通常、出力をバッファリングするため、出力のすべてのビットに対してシステム コールを行うことはありません。 による
出力が節約されるため、コストのかかるシステムコールが少なくなります。 たとえば、このちょっとした部分で
コードの内容を確認するために、処理する行ごとに画面にドットを出力したいとします。
プログラムの進捗状況。 Perl は、行ごとにドットを表示するのではなく、出力をバッファリングします。
50 個のドットの列が一度に表示されるまでには、長い待ち時間がかかります。

# 長く待ってから、一度にドットの列を並べる
while(<>){
「.」を印刷します。
++$count % 50 でない限り、「\n」を出力します。

#... 負荷の高い行処理操作
}

これを回避するには、出力ファイルハンドル (この場合は「STDOUT」) のバッファリングを解除する必要があります。
特殊変数 $| を設定できます。 true 値 (ニーモニック: ファイルハンドルの作成)
「熱々」):

$|++;

# すぐにドットが表示される
while(<>){
「.」を印刷します。
++$count % 50 でない限り、「\n」を出力します。

#... 負荷の高い行処理操作
}

$| ファイルハンドルごとの特殊変数の XNUMX つであるため、各ファイルハンドルには独自のコピーがあります。
その価値について。 たとえば、標準出力と標準エラーをマージしたい場合は、次のようにします。
それぞれをバッファリング解除する必要があります (ただし、STDERR はデフォルトでバッファリングされていない可能性があります)。

{
私の $previous_default = select(STDOUT); # 以前のデフォルトを保存
$|++; # 自動フラッシュ STDOUT
選択(STDERR);
$|++; # STDERR を自動フラッシュします (念のため)
select($previous_default); # 以前のデフォルトに戻す
}

# 今度は交互に実行する必要があります。 そして+
while(1){
睡眠1;
標準出力 "." を出力します。
STDERR "+" を出力します。
++$count % 25 でない限り、STDOUT "\n" を出力します。
}

$| のほかに特別な変数を使用すると、「binmode」を使用してファイルハンドルに「:unix」を与えることができます。
バッファリングされていないレイヤー:

binmode( STDOUT, ":unix" );

while(1){
睡眠1;
「.」を印刷します。
++$count % 50 でない限り、「\n」を出力します。
}

出力層の詳細については、「binmode」のエントリを参照し、perlfunc で開きます。
PerlIO モジュールのドキュメント。

IO::Handle またはそのサブクラスの XNUMX つを使用している場合は、「autoflush」メソッドを呼び出すことができます。
ファイルハンドルの設定を変更するには:

IO::ハンドルを使用します。
my( $io_fh )、">"、"output.txt" を開きます。
$io_fh->自動フラッシュ(1);

IO::Handle オブジェクトには「flush」メソッドもあります。 いつでもバッファをフラッシュできます。
自動バッファリングなしで欲しい

$io_fh->フラッシュ;

認定条件 do I 変化する、 消去、 or insert a ライン in a ファイル、 or アペンド 〜へ   初め of a ファイル?
(ブライアン・ド・フォイによる寄稿)

テキスト ファイルへの行の挿入、変更、または削除の基本的な考え方には、次のことが含まれます。
変更を加えたい箇所までファイルを読み取って印刷し、変更を加えます。
次に、ファイルの残りの部分を読み取って印刷します。 Perl はランダムアクセスを提供しません
行 (特にレコード入力区切り文字 $/ は変更可能であるため)、ただしそのようなモジュールは
Tie::File はそれを偽装できるためです。

これらのタスクを実行する Perl プログラムは、ファイルを開いてそのファイルを出力するという基本的な形式をとります。
行を閉じてファイルを閉じます。

$in、'<'、$file を開くか、「古いファイルを読み取れません: $!」を選択してください。
$out、'>'、"$file.new" を開くか、"新しいファイルを書き込めません: $!";

while( <$in> ) {
$out $_ を印刷します。
}

$out を閉じます。

その基本フォーム内に、行の挿入、変更、削除が必要な部分を追加します。

先頭に行を追加するには、印刷するループに入る前にそれらの行を印刷します。
既存のライン。

$in、'<'、$file を開くか、「古いファイルを読み取れません: $!」を選択してください。
$out、'>'、"$file.new" を開くか、"新しいファイルを書き込めません: $!";

print $out "# この行を先頭に追加します\n"; # <--- これが魔法です

while( <$in> ) {
$out $_ を印刷します。
}

$out を閉じます。

既存の行を変更するには、「while」ループ内の行を変更するコードを挿入します。 で
この場合、コードは「perl」の小文字バージョンをすべて検索し、大文字に変換します。 の
はすべての行で発生するため、必ずすべての行でこれを行うようにしてください。

$in、'<'、$file を開くか、「古いファイルを読み取れません: $!」を選択してください。
$out、'>'、"$file.new" を開くか、"新しいファイルを書き込めません: $!";

print $out "# この行を先頭に追加します\n";

while( <$in> ) {
s/\b(perl)\b/Perl/g;
$out $_ を印刷します。
}

$out を閉じます。

特定の行のみを変更するには、入力行番号 $. が便利です。 まず読んで、
変更したい行までを出力します。 次に、読みたい単一行を読み取ります
変更して、変更して、印刷してください。 その後、残りの行を読み取って出力します。

while( <$in> ) { # 変更前の行を出力します
$out $_ を印刷します。
$ の場合は最後です。 == 4; # 変更前の行番号
}

私の $line = <$in>;
$line =~ s/\b(perl)\b/Perl/g;
$out $line を出力します。

while( <$in> ) { # 残りの行を出力します
$out $_ を印刷します。
}

行をスキップするには、ループ コントロールを使用します。 この例の「next」はコメント行をスキップします。
そして、「最後の」は、「__END__」または「__DATA__」のいずれかに遭遇すると、すべての処理を停止します。

while( <$in> ) {
次の場合 /^\s+#/; # コメント行をスキップします
last if /^__(END|DATA)__$/; # コードの終わりで停止マーカー
$out $_ を印刷します。
}

「next」を使用して行をスキップして、特定の行を削除するのと同じようなことを行います。
出力には表示したくないのです。 この例では、XNUMX 行ごとにスキップします。

while( <$in> ) {
$ でない場合は次へ。 %5;
$out $_ を印刷します。
}

何らかの奇妙な理由で、ファイル全体を一度に見たい場合は、
行ごとに処理するので、丸ごと飲み込むことができます(全体を収まる限り)
メモリ!):

$in、'<'、$file を開くか、死ぬか「古いファイルを読み取れません: $!」
$out、'>'、"$file.new" を開くか、"新しいファイルを書き込めません: $!";

my $content = do {ローカル $/; <$in> }; # 啜る!

# ここで魔法をかけてください

$out $content を印刷します。

Path::Tiny や Tie::File などのモジュールもこれに役立ちます。 ただし、できれば、
ファイル全体を一度に読み取らないようにしてください。 Perl はそのメモリをオペレーティングシステムに返しません。
プロセスが完了するまでシステムを停止します。

Perl ワンライナーを使用してファイルをその場で変更することもできます。 以下はすべてを変更します
「フレッド」から「バーニー」へ ファイル.txt内、ファイルを新しい内容で上書きします。 とともに
「-p」スイッチ。Perl は、「-e」および「-i」で指定したコードの周囲に「while」ループをラップします。
インプレイス編集をオンにします。 現在の行は $_ にあります。 「-p」を指定すると、Perl は自動的に出力します。
ループの終わりの $_ の値。 詳細については、perlrun を参照してください。

perl -pi -e 's/Fred/Barney/' inFile.txt

「inFile.txt」のバックアップを作成するには、「-i」にファイル拡張子を付けて追加します。

perl -pi.bak -e 's/Fred/Barney/' inFile.txt

XNUMX 行目のみを変更するには、入力行番号である $. をチェックするテストを追加して、
テストに合格した場合にのみ操作を実行します。

perl -pi -e 's/Fred/Barney/ if $。 == 5' inFile.txt

特定の行の前に行を追加するには、Perl が $_ を出力する前に XNUMX 行 (または複数行!) 追加します。

perl -pi -e 'print "3 行目の前に置く\n" if $. == XNUMX' inFile.txt

現在の行はファイルの先頭に出力されるため、ファイルの先頭に行を追加することもできます。
ループの終わり:

perl -pi -e 'print "最初の行の前に置く\n" if $. == 1' ファイル.txt内

ファイル内に既にある行の後に行を挿入するには、「-n」スイッチを使用します。 ちょうど「-p」みたいな感じです
ただし、ループの最後に $_ が出力されないため、自分で行う必要があります。
この場合、最初に $_ を出力し、次に追加する行を出力します。

perl -ni -e 'print; print "5 行目の後に置く\n" if $. == XNUMX' inFile.txt

行を削除するには、必要な行のみを印刷します。

perl -ni -e 'print if /d/' inFile.txt

認定条件 do I カウント   of ライン in a ファイル?
(ブライアン・ド・フォイによる寄稿)

概念的には、ファイル内の行を数える最も簡単な方法は、単純に行を読み取って、
それらを数える:

私の$ count = 0;
while( <$fh> ) { $count++; }

ただし、Perl がすでにそれを行っているため、実際に自分でカウントする必要はありません。
ドル。 変数。最後に読み取られたファイルハンドルからの現在の行番号です。

1 while( <$fh> );
私の $count = $.;

$. を使用したい場合は、次のような単純な XNUMX ライナーに減らすことができます。

% perl -lne '} print $.; {' ファイル

% perl -lne 'END { print $. }' ファイル

ただし、それらはかなり非効率的になる可能性があります。 それらが十分に速くない場合は、次のようにすることもできます。
データのチャンクを読み取り、改行の数をカウントします。

私の $lines = 0;
open my($fh), '<:raw', $filename or die "$filename を開けません: $!";
while( sysread $fh, $buffer, 4096 ) {
$lines += ( $buffer =~ tr/\n// );
}
$fhを閉じます。

ただし、行末が改行でない場合は機能しません。 それを変えるかもしれない
「tr///」を「s///」に変更すると、入力レコード区切り文字 $/ の回数をカウントできます。
現れます:

私の $lines = 0;
open my($fh), '<:raw', $filename or die "$filename を開けません: $!";
while( sysread $fh, $buffer, 4096 ) {
$lines += ( $buffer =~ s|$/||g; );
}
$fhを閉じます。

シェルアウトを気にしない場合は、通常、「wc」コマンドが最も高速です。
余分なプロセス間のオーバーヘッド。 ただし、ファイル名が汚染されていないことを確認してください。

#!perl -T

$ENV{PATH} = undef;

私の $lines;
if( $filename =~ /^([0-9a-z_.]+)\z/ ) {
$lines = `/ usr / bin / wc -l $1`
$lines をむしゃむしゃ食べます。
}

認定条件 do I 削除   last N ライン から a ファイル?
(ブライアン・ド・フォイによる寄稿)

概念的な最も簡単な解決策は、ファイル内の行を数えて、その行から開始することです。
行数 (最後の N を引いたもの) を新しいファイルに出力します。

ほとんどの場合、本当の問題は、追加の行を追加せずに最後の N 行を削除するにはどうすればよいかということです。
ファイルを XNUMX 回渡すよりも、または大量のコピーを行わずに実行する方法を説明します。 簡単なコンセプトは、
ファイルに数百万行が含まれる可能性がある場合の厳しい現実。

XNUMX つのトリックは、ファイルの最後から開始する File::ReadBackwards を使用することです。 そのモジュール
実際のファイルハンドルをラップして簡単に移動できるようにするオブジェクトを提供します。
ファイル。 必要な場所に到達したら、実際のファイルハンドルを取得して作業できます。
それを通常どおりにします。 この場合、最後の行の末尾でファイルの位置を取得します。
ファイルをその時点まで保持して切り詰めたい場合:

File::ReadBackwards を使用します。

私の $filename = 'test.txt';
私の $Lines_to_truncate = 2;

my $bw = File::ReadBackwards->new( $filename )
または、「[$filename] を逆方向に読み取れませんでした: $!」;

私の $lines_from_end = 0;
until( $bw->eof または $lines_from_end == $Lines_to_truncate ) {
print "取得: ", $bw->readline;
$lines_from_end++;
}

truncate( $filename, $bw->tell );

File::ReadBackwards モジュールには、入力レコードを設定するという利点もあります。
正規表現の区切り文字。

Tie::File モジュールを使用すると、結合されたファイルを通じて行にアクセスできます。
配列。 通常の配列操作を使用して、最後の配列の設定など、ファイルを変更できます。
インデックスを作成し、「スプライス」を使用します。

認定条件 できる I つかいます Perlの "-私" オプション から 以内 a プログラム?
「-i」は Perl の $^I 変数の値を設定します。これは、「<>」の動作に影響します。
詳細については、perlrun を参照してください。 適切な変数を直接変更すると、次のようになります。
より大きなプログラム内でも同じ動作が行われます。 例えば:

#..。
{
local($^I, @ARGV) = ('.orig', glob("*.c"));
while (<>) {
if ($. == 1) {
print "この行は各ファイルの先頭に表示されるはずです\n";
}
s/\b(p)earl\b/${1}erl/i; # 大文字と小文字を区別せずにタイプミスを修正します
印刷;
eof の場合は ARGV を閉じます。 # $をリセットします。
}
}
# $^I と @ARGV はここで古い値に戻ります

このブロックは、現在のディレクトリ内のすべての「.c」ファイルを変更し、そのバックアップを残します。
各ファイルの元のデータを新しい「.c.orig」ファイルに保存します。

認定条件 できる I copy a ファイル?
(ブライアン・ド・フォイによる寄稿)

File::Copy モジュールを使用します。 Perl が付属しており、ファイル システム間で真のコピーを実行できます。
そしてそれは、ポータブルな方法でその魔法を発揮します。

ファイル::コピーを使用します。

copy( $original, $new_copy ) または die "コピーに失敗しました: $!";

File::Copy を使用できない場合は、自分で作業を行う必要があります。元のファイルを開いて、
宛先ファイルを開いて、オリジナルを読みながら宛先ファイルに印刷します。
また、アクセス許可、所有者、およびグループを新しいファイルに忘れずにコピーする必要があります。

認定条件 do I make a 一時的 file 名?
ファイルの名前を知る必要がない場合は、「undef」を指定して「open()」を使用できます。
ファイル名の。 Perl 5.8 以降では、「open()」関数は匿名の
一時ファイル:

$tmp、'+>'、undef または die $! を開きます。

それ以外の場合は、File::Temp モジュールを使用できます。

File::Temp qw/ tempfile tempdir /; を使用します。

私の $dir = tempdir( CLEANUP => 1 );
($fh, $filename) = tempfile( DIR => $dir );

# またはファイル名を知る必要がない場合

私の $fh = tempfile( DIR => $dir );

File::Temp は Perl 5.6.1 以降の標準モジュールです。 最新のものをお持ちでない場合は、
十分な Perl がインストールされている場合は、IO::File モジュールの「new_tmpfile」クラス メソッドを使用して取得します。
読み取りと書き込みのために開かれたファイルハンドル。 ファイルの内容を知る必要がない場合に使用してください。
名前:

IO::Fileを使用します。
私の $fh = IO::File->new_tmpfile()
または、「新しい一時ファイルを作成できません: $!」;

一時ファイルを手動で作成する場合は、プロセス ID や
現在の時間値。 XNUMX つのプロセスに多くの一時ファイルが必要な場合は、
カウンター:

ベギン {
Fcntlを使用します。
ファイル::仕様を使用します。
私の $temp_dir = File::Spec->tmpdir();
私の $file_base = sprintf "%d-%d-0000", $$, 時間;
私の $base_name = File::Spec->catfile($temp_dir, $file_base);

サブtemp_file {
私の$fh;
私の$ count = 0;
until( 定義(ファイル番号($fh)) || $count++ > 100 ) {
$base_name =~ s/-(\d+)$/"-" 。 (1 + $1)/e;
# セキュリティ上の理由から O_EXCL が必要です。
sysopen $fh, $base_name, O_WRONLY|O_EXCL|O_CREAT;
}

if( 定義されたファイル番号($fh) ) {
return ($fh, $base_name);
}
他{
戻る ();
}
}
}

認定条件 できる I 操作する 固定レコード長 ファイル?
最も効率的な方法は、 パック() および unpack()。 これは使用するよりも高速です substr()
非常に多くの文字列を取得する場合。 ほんの少しだけ遅いです。

これは、固定フォーマットを分割して再度組み立てるためのコードのサンプルチャンクです。
入力行。この場合は、通常のバークレー スタイル ps の出力からのものです。

# 入力行のサンプル:
# 15158 p5 T 0:00 perl /home/tchrist/scripts/now-what
私の $PS_T = 'A6 A4 A7 A5 A*';
私の $ps, '-|', 'ps' を開きます。
スカラー <$ps> を出力します。
my @fields = qw( pid tt stat time コマンド );
while (<$ps>) {
私の%プロセス;
@process{@fields} = unpack($PS_T, $_);
私の $field ( @fields ) {
print "$field: <$process{$field}>\n";
}
print 'line=', Pack($PS_T, @process{@fields} ), "\n";
}

各行のフィールドを簡単に処理するために、ハッシュ スライスを使用しました。 保管する
配列内のキーを使用すると、キーをグループとして操作したり、「for」でループしたりすることが簡単になります。
また、グローバル変数やシンボリック参照を使用してプログラムを汚染することも避けられます。

認定条件 できる I make a ファイルハンドル ローカル 〜へ a サブルーチン? 認定条件 do I パス ファイルハンドル の間に
サブルーチン? 認定条件 do I make an 配列 of ファイルハンドル?
perl5.6以降では、 開いた() ファイルとディレクトリのハンドルを渡すと、参照としてファイルとディレクトリのハンドルが自動的に有効化されます。
初期化されていないスカラー変数。 その後、これらの参照を他の参照と同じように渡すことができます。
スカラーを作成し、名前付きハンドルの代わりに使用します。

私の $fh、$file_name を開きます。

ローカル $fh、$file_name を開きます。

print $fh "Hello World!\n";

プロセスファイル( $fh );

必要に応じて、これらのファイルハンドルを配列またはハッシュに保存できます。 それらにアクセスすると、
直接的には、それらは単純なスカラーではないため、「print」に少し助けを与える必要があります。
中かっこ内のファイルハンドル参照。 Perl は、次の場合にのみそれを自力で理解できます。
ファイルハンドル参照は単純なスカラーです。

私の @fhs = ( $fh1, $fh2, $fh3 );

for( $i = 0; $i <= $#fhs; $i++ ) {
print {$fhs[$i]} "単なる Perl の答えです、\n";
}

perl5.6 より前は、古いバージョンで見られるさまざまな typeglob イディオムに対処する必要がありました。
コー​​ド。

ファイルを開きます、> $ファイル名";
process_typeglob( *FILE );
プロセス参照( \*FILE );

sub process_typeglob {ローカル *FH = シフト; print FH "タイプグロブ!" }
サブプロセスリファレンス { ローカル $fh = シフト; print $fh "参考に!" }

多数の匿名ハンドルを作成したい場合は、シンボルまたは
IO::ハンドルモジュール。

認定条件 できる I つかいます a ファイルハンドル 間接的に?
間接ファイルハンドルとは、ファイルハンドルが必要な場所でシンボル以外のものを使用することです。
ファイルハンドルが期待されます。 間接的なファイルハンドルを取得する方法は次のとおりです。

$fh = SOME_FH; # bareword は strict-subs に敵対的です
$fh = "SOME_FH"; # strict-refs 敵対的; 同じパッケージのみ
$fh = *SOME_FH; # タイプグロブ
$fh = \*SOME_FH; # typeglob への参照 (bless-able)
$fh = *SOME_FH{IO}; # *SOME_FH typeglob からの IO::Handle の祝福

または、IO::* モジュールの XNUMX つから「new」メソッドを使用して、匿名の
ファイルハンドルを取得し、それをスカラー変数に保存します。

IO::ハンドルを使用します。 #5.004以上
私の $fh = IO::Handle->new();

その後、通常のファイルハンドルと同様に、これらのいずれかを使用します。 Perl が期待している場所ならどこでも
ファイルハンドルの代わりに、間接的なファイルハンドルを使用することもできます。 間接的なファイルハンドルは単なる
ファイルハンドルを含むスカラー変数。 「印刷」、「開く」、「シーク」、または
」 " ダイヤモンド演算子は、名前付きファイルハンドルまたはスカラー変数を受け入れます
XNUMX つを含む:

($ifh、$ofh、$efh) = (*STDIN、*STDOUT、*STDERR);
print $ofh "入力してください: ";
私の $got = <$ifh>
print $efh "それは何でしたか: $got";

ファイルハンドルを関数に渡す場合は、次の XNUMX つの方法で関数を作成できます。

サブaccept_fh {
私の $fh = シフト;
print $fh "間接ファイルハンドルに送信中\n";
}

または、typeglob をローカライズしてファイルハンドルを直接使用することもできます。

サブaccept_fh {
ローカル *FH = シフト;
print FH "ローカライズされたファイルハンドルに送信中\n";
}

どちらのスタイルも、実際のファイルハンドルのオブジェクトまたはタイプグロブで動作します。 (彼らはまた、
状況によっては文字列を扱うこともできますが、これには危険が伴います。)

accept_fh(*STDOUT);
accept_fh($ハンドル);

上記の例では、ファイルハンドルを使用する前にスカラー変数に割り当てました。
これは、単純なスカラー変数のみが使用され、ハッシュの式や添字は使用されないためです。
配列は、「print」、「printf」、またはダイヤモンド演算子のような組み込みで使用できます。 使用する
ファイルハンドルとして単純なスカラー変数以外のものは不正であり、
コンパイル:

私の @fd = (*STDIN、*STDOUT、*STDERR);
print $fd[1] "入力してください: "; # 間違っている
私の $got = <$fd[0]> # 間違っています
print $fd[2] "それは何でしたか: $got"; # 間違っている

「print」と「printf」では、ブロックと式を使用してこれを回避します。
ファイルハンドルを配置します。

print { $fd[1] } "面白いもの\n";
printf { $fd[1] } "かわいそうな %x を憐れんでください。\n", 3_735_928_559;
# 哀れなデッドビーフが可哀想だ。

このブロックは他のブロックと同様に適切なブロックであるため、より複雑なコードをそこに配置できます。
これにより、次の XNUMX つの場所のいずれかにメッセージが送信されます。

私の $ok = -x "/ bin / cat";
print { $ok ? $fd[1] : $fd[2] } "猫の統計 $ok\n";
print { $fd[ 1+ ($ok || 0) ] } "猫の統計 $ok\n";

「print」と「printf」をオブジェクト メソッド呼び出しのように扱うこのアプローチは、
ダイヤモンドのオペレーター。 これは、単なる関数ではなく、実際の演算子であるためです。
カンマのない引数。 私たちと同じようにタイプグロブを構造体に保存していると仮定します。
上記では、「readline」という名前の組み込み関数を使用して、レコードを「<>」と同じように読み取ることができます。
そうです。 上記の @fd の初期化を考慮すると、これは機能しますが、それは次の理由によるものです。
読み込まれた行() タイプグロブが必要です。 オブジェクトや文字列では機能しません。
まだ修正されていないバグ。

$got = readline($fd[0]);

間接的なファイルハンドルの不安定さは、
それらは文字列、タイプグロブ、オブジェクト、またはその他のものです。 基本的な構文です
オペレーター。 オブジェクトゲームをプレイしても、ここではまったく役に立ちません。

認定条件 できる I セッションに up a フッター 形式でアーカイブしたプロジェクトを保存します. 〜へ be 中古   書く()?
これを行うための組み込みの方法はありませんが、perlform にはそれを行うためのテクニックがいくつかあります。
勇敢なハッカーにはそれが可能です。

認定条件 できる I 書く() a ストリング?
(ブライアン・ド・フォイによる寄稿)

文字列に「書き込み」たい場合は、次のようにするだけです。 ファイルハンドルを文字列に、
Perl 5.6 以降、Perl では次のことが可能になりました。

FH、'>'、\my $string を開きます。
書き込み( FH );

あなたは優れたプログラマになりたいので、おそらく字句ファイルハンドルを使用したいと思うでしょう。
フォーマットはデフォルトからベアワードファイルハンドルで動作するように設計されていますが、
形式名にはファイルハンドル名が使用されます。 ただし、これは Perl を使用して制御できます。
ファイルハンドルごとの特別な変数: $^ (ページの先頭の形式に名前を付ける)、および $~ (ページの先頭の形式に名前を付ける)
行フォーマットを示します。 これらの変数を設定するには、デフォルトのファイルハンドルを変更する必要があります。

my($fh)、'>'、\my $string を開きます。

{ # ファイルハンドルごとの変数を設定する
私の $old_fh = select( $fh );
$~ = '動物';
$^ = 'ANIMAL_TOP';
select( $old_fh );
}

形式 ANIMAL_TOP =
ID タイプ名
.

形式 ANIMAL =
@## @<<< @<<<<<<<<<<<<<
$id、$type、$name
.

write は字句変数またはパッケージ変数を使用できますが、使用する変数はどれも
形式の範囲に設定します。 それはおそらく、いくつかのパッケージをローカライズする必要があることを意味します
変数:

{
local( $id, $type, $name ) = qw( 12 キャットバスター );
書き込み( $fh );
}

$ stringを出力します。

「formline」とアキュムレータ変数を使ってできるトリックもいくつかあります。
$^A ただし、「formline」はページングを処理しないため、フォーマットの価値の多くが失われます。
すぐ。 フォーマットを使用すると、最終的には再実装することになります。

認定条件 できる I 開いた a ファイルハンドル 〜へ a ストリング?
(ピーター J. ホルツァーによる寄稿、 [メール保護])

Perl 5.8.0 以降、文字列を参照するファイル ハンドルは、
ファイル名の代わりにその文字列への参照。 このファイル ハンドルは次の目的で使用できます。
文字列の読み取りまたは書き込み:

open(my $fh, '>', \$string) または die "書き込み用に文字列を開けませんでした";
print $fh "foo\n";
print $fh "バー\n"; # $string には「foo\nbar\n」が含まれるようになりました

open(my $fh, '<', \$string) または die "文字列を読み取り用に開くことができませんでした";
私の $x = <$fh>; # $x には「foo」が含まれるようになりました\n

Perl の古いバージョンでは、IO::String モジュールが同様の機能を提供します。

認定条件 できる I 出力 my 番号   コンマ 追加した?
(brian d foy と Benjamin Goldberg による寄稿)

Number::Format を使用して、数値内の位置を区切ることができます。 ロケール情報を扱います
代わりに句点を挿入したい人 (またはその他の何かを挿入したい人向け)
使ってください、本当に)。

このサブルーチンは番号にカンマを追加します。

サブコミット {
ローカル$_=シフト;
1 while s/^([-+]?\d+)(\d{3})/$1,$2/;
$_を返します。
}

Benjamin Goldberg による次の正規表現は、数値にカンマを追加します。

s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d) )/$1、/g;

コメントを付けると見やすくなります。

s/(
^[-+]? # 番号の始まり。
\d+? # 最初のカンマの前の最初の桁
(?= # の後に , (ただし、一致には含まれません) :
(?>(?:\d{3})+) # XNUMX 桁の正の倍数。
(?!\d) # x * 3 + 1 などではなく、*正確な*倍数。
)
| # または:
\G\d{3} # 最後のグループの後に、XNUMX 桁の数字を取得します
(?=\d) # ただし、その後にさらに多くの数字が必要です。
)/$1、/xg;

認定条件 できる I 翻訳する アクセント (〜) in a ファイル名?
perlfunc に記載されている <> ("glob()") 演算子を使用します。 5.6 より古いバージョンの Perl
チルダを理解するシェルがインストールされている必要があります。 Perl の新しいバージョンには、
この機能は組み込まれています。 File::KGlob モジュール (CPAN から入手可能) により、移植性がさらに高まります。
グロブ機能。

Perl 内では、これを直接使用できます。

$ファイル名 =~ s{
^ ~ # 先頭のチルダを検索します
( # これを $1 に保存します
[^/] # スラッシュ以外の文字
* # 0 回以上繰り返します (0 は私を意味します)
)
}{
$1
? (getpwnam($1))[7]
: ( $ENV{HOME} || $ENV{LOGDIR} )
}元;

認定条件 来ます いつ I 開いた a file 読み書き it ワイプ it でる?
ファイルを切り詰めるこのようなものを使用しているため その後 あなたに読書を与えます-
書き込みアクセス:

$fh、'+>'、'/path/name' を開きます。 # 間違っています (ほぼ常に)

おっと。 代わりにこれを使用する必要がありますが、ファイルが存在しない場合は失敗します。

$fh、'+<'、'/path/name' を開きます。 # アップデートのために開いています

「">」を使用すると、常に破壊または作成されます。 「<」を使用しても、そのようなことはありません。 「+」は変わらない


ここでは、さまざまな種類のファイルを開く例を示します。 「sysopen」を使用する人は皆、次のように想定しています。
Fcntl から定数を取得しました。

Fcntlを使用します。

ファイルを読み取り用に開くには:

$fh、'<'、$path を開くか $!;
sysopen my $fh、$path、O_RDONLY または die $!;

書き込み用にファイルを開くには、必要に応じて新しいファイルを作成するか、古いファイルを切り詰めます。

$fh、'>'、$path を開くか $!;
$fh、$path、O_WRONLY|O_TRUNC|O_CREAT を sysopen するか、$!;
$fh、$path、O_WRONLY|O_TRUNC|O_CREAT、0666 を sysopen するか、$!;

書き込み用にファイルを開くには、新しいファイルを作成します。ファイルは存在してはいけません。

$fh、$path、O_WRONLY|O_EXCL|O_CREAT を sysopen するか、$!;
$fh、$path、O_WRONLY|O_EXCL|O_CREAT、0666 を sysopen するか、$!;

追加するためにファイルを開くには、必要に応じて以下を作成します。

$fh、'>>' $path を開くか、$!;
$fh、$path、O_WRONLY|O_APPEND|O_CREAT を sysopen するか、$!;
sysopen my $fh, $path, O_WRONLY|O_APPEND|O_CREAT, 0666 or die $!;

追加するためにファイルを開くには、ファイルが存在する必要があります:

sysopen my $fh、$path、O_WRONLY|O_APPEND または die $!;

更新するためにファイルを開くには、ファイルが存在する必要があります:

$fh、'+<'、$path を開くか $!;
$fh、$path、O_RDWR を sysopen するか、$!;

更新するためにファイルを開くには、必要に応じてファイルを作成します。

sysopen my $fh、$path、O_RDWR|O_CREAT または die $!;
$fh、$path、O_RDWR|O_CREAT、0666 を sysopen するか、$!;

更新するためにファイルを開くには、ファイルが存在してはなりません:

$fh、$path、O_RDWR|O_EXCL|O_CREAT を sysopen するか、$!;
$fh、$path、O_RDWR|O_EXCL|O_CREAT、0666 を sysopen するか、$!;

ブロックせずにファイルを開くには、必要に応じて作成します。

sysopen my $fh, '/foo/somefile', O_WRONLY|O_NDELAY|O_CREAT
さもなければ、「/foo/somefile を開けません: $!」:

ファイルの作成も削除もアトミックであることが保証されていないことに注意してください。
NFS 経由の操作。 つまり、XNUMX つのプロセスがどちらも正常に作成またはリンク解除される可能性があります。
同じファイルです! したがって、O_EXCL は期待されているほど排他的ではありません。

ペルロペントゥトも参照。

なぜ do I 時々 取得する an "口論 リスト あまりに 長さ" いつ I つかいます <*>?
「<>」演算子はグロビング操作を実行します (上記を参照)。 以前の Perl バージョンでは
v5.6.0 よりも内部 glob() オペレーターフォーク CSH(1) 実際のグロブ展開を行うには、
ただし、csh は 127 を超える項目を処理できないため、「引数リストが多すぎる」というエラー メッセージが表示されます。
tcsh を csh としてインストールした人にはこの問題は発生しませんが、そのユーザーには問題が発生する可能性があります。
それに驚いた。

これを回避するには、Perl v5.6.0 以降にアップグレードし、次のようにグロブを自分で実行します。
readdir() とパターンを使用するか、シェルを使用しない File::Glob のようなモジュールを使用します。
グロビングを行います。

認定条件 できる I 開いた a file   a 主要な >" or 引きずります ブランク?
(ブライアン・マッコーリー氏による寄稿)

Perl の特別な XNUMX 引数形式 開いた() 関数は末尾の空白を無視します
ファイル名を検索し、先頭の特定の文字 (または末尾の "|") からモードを推測します。 で
Perl の古いバージョンはこれが唯一のバージョンでした 開いた() そしてそれは古い時代に蔓延しています
コードと本。

XNUMX つの引数形式を使用する特別な理由がない限り、XNUMX つの引数形式を使用する必要があります。
の引数形式 開いた() ファイル名の文字を特別なものとして扱いません。

$fh、"<"、" ファイル " を開きます。 # ファイル名は「ファイル」です
$fh, ">", ">ファイル" を開きます。 # ファイル名は「">ファイル」です

認定条件 できる I 確実に リネーム a ファイル?
オペレーティング システムが適切な機能をサポートしている場合は、 mv(1) ユーティリティまたは同等の機能、
これは動作します:

rename($old, $new) または system("mv", $old, $new);

代わりに File::Copy モジュールを使用する方が移植性が高い場合があります。 新しいものにコピーするだけです
ファイルを新しい名前に変更し (戻り値を確認)、古いファイルを削除します。 これは実際にはそうではありません
意味的には「rename()」と同じで、権限などのメタ情報を保持します。
タイムスタンプ、i ノード情報など。

認定条件 できる I ロック a ファイル?
Perl の組み込み 群れ() 関数 (詳細については perlfunc を参照) が呼び出されます。 群れ(2) そうなった場合
存在し、 fcntl(2) そうでない場合 (Perl バージョン 5.004 以降)、および ロック(3) どちらでもない場合
前の XNUMX つのシステム コールのうちの XNUMX つが存在します。 一部のシステムでは、別のものが使用される場合もあります。
ネイティブ ロックの形式。 Perl に関する注意点をいくつか示します。 群れ():

1. XNUMX つのシステム コール (またはそれに近い同等のシステム コール) がいずれも実行されない場合、致命的なエラーが生成されます。
存在しています。

2. ロック(3) 共有ロックは提供されず、ファイルハンドルが開いている必要があります。
書き込み(または追加、または読み取り/書き込み)。

3. 一部のバージョン 群れ() ネットワーク上でファイルをロックすることはできません (NFS ファイル システムなど)。
したがって、強制的に使用する必要があります fcntl(2) Perl をビルドするとき。 しかし、これさえも
よく言っても疑わしい。 perlfunc の flock エントリと、 INSTALL ソース内のファイル
これを行うための Perl の構築に関する情報については、ディストリビューションを参照してください。

潜在的に明白ではないものの、従来の flock セマンティクスが XNUMX つあります。それは、待機することです。
ロックが許可され、そのロックが解除されるまで無期限に 単に アドバイザリー。 このような
任意ロックはより柔軟ですが、提供される保証は少なくなります。 この意味は
でロックされたファイル 群れ() を使用しないプログラムによって変更される可能性があります。 群れ().
赤信号で止まる車同士は仲良くできますが、赤信号で止まる車とはそうではありません。
赤信号でも止まらないでください。 perlport マンページを参照してください。ポート固有の
詳細については、ドキュメント、またはシステム固有のローカルマンページを参照してください。 仮定するのが一番良い
移植可能なプログラムを作成している場合は、従来の動作となります。 (そうでない場合は、そうすべきです
いつものように、自分のシステムの特異性について完全に自由に書いてください (場合によっては
「機能」と呼ばれます)。 移植性への配慮を甘んじて追求する必要はありません。
仕事をやり遂げる方法。)

ファイル ロックの詳細については、perlopentut の「ファイル ロック」も参照してください。
それを持っています(5.6の新機能)。

なぜ することはできません I ただ オープン(FH、 ">file.lock")?
よくあるコードの一部 NOT USE これは:

眠る(3) while -e 'file.lock'; # 使用しないでください
$lock、'>'、'file.lock' を開きます。 # この壊れたコード

これは古典的な競合状態です。つまり、XNUMX つのステップを実行して、実行する必要があることを実行します。
XNUMXつ。 そのため、コンピューター ハードウェアはアトミックなテスト アンド セット命令を提供します。 理論的には、
これは機能するはずです:

sysopen my $fh, "file.lock", O_WRONLY|O_EXCL|O_CREAT
さもなければ、「file.lockを開けません: $!」;

ただし、残念なことに、ファイルの作成 (および削除) は NFS 上ではアトミックではないため、これは機能しません。
(毎回ではありませんが、少なくとも) ネット経由で作業します。 関わるさまざまなスキーム リンク() されている
と提案されていますが、これらはビジー待機を伴う傾向があり、これも望ましいとは言えません。

I まだ しない 取得する ロック。 I ただ 欲しいです 〜へ 増加   in   ファイルにソフトウェアを指定する必要があります。 認定条件 できる I do この?
ウェブページのヒットカウンターは役に立たない、なんて誰も言っていませんでしたか? 彼らは数を数えません
それらは時間の無駄であり、作家の虚栄心を刺激するだけです。 その
乱数を選択する方が良いでしょう。 それらはより現実的です。

とにかく、自分自身を助けることができない場合は、これができることです。

Fcntl qw(:DEFAULT :flock); を使用します。
sysopen my $fh, "numfile", O_RDWR|O_CREAT or die "numfile: $!" を開けません。
flock $fh、LOCK_EX、または die "ファイル番号をロックできません: $!";
私の $num = <$fh> || 0;
Seek $fh, 0, 0 or die "ファイル番号を巻き戻すことができません: $!";
truncate $fh, 0 or die "can't truncate numfile: $!";
(print $fh $num+1, "\n") または die "numfile: $!" を書き込めません。
$fh を閉じるか死ぬか "ファイル番号: $! を閉じることができません。";

これは、はるかに優れた Web ページ ヒット カウンタです。

$hits = int( (time() - 850_000_000) / ランド(1_000) );

カウントが友人に感銘を与えない場合は、コードに感銘を受ける可能性があります。 :-)

すべて I 欲しいです 〜へ do is アペンド a 小さい of 클라우드 기반 AI/ML및 고성능 컴퓨팅을 통한 디지털 트윈의 기초 – Edward Hsu, Rescale CPO 많은 엔지니어링 중심 기업에게 클라우드는 R&D디지털 전환의 첫 단계일 뿐입니다. 클라우드 자원을 활용해 엔지니어링 팀의 제약을 해결하는 단계를 넘어, 시뮬레이션 운영을 통합하고 최적화하며, 궁극적으로는 모델 기반의 협업과 의사 결정을 지원하여 신제품을 결정할 때 데이터 기반 엔지니어링을 적용하고자 합니다. Rescale은 이러한 혁신을 돕기 위해 컴퓨팅 추천 엔진, 통합 데이터 패브릭, 메타데이터 관리 등을 개발하고 있습니다. 이번 자리를 빌려 비즈니스 경쟁력 제고를 위한 디지털 트윈 및 디지털 스레드 전략 개발 방법에 대한 인사이트를 나누고자 합니다. 〜へ   end of a ファイルにソフトウェアを指定する必要があります。 Do I まだ 持ってる 〜へ つかいます
ロック?
「flock」を正しく実装しているシステムを使用していて、次の例を使用すると、
「perldoc -f flock」のコードは、使用している OS がそうでない場合でも、すべて問題ありません。
追加モードを正しく実装します (そのようなシステムが存在する場合)。 それで、制限してもよければ
「flock」を実装する OS に自分自身を接続してください (これは実際には大きな制限ではありません)。
それがあなたがすべきことです。

追加を正しく実装するシステムのみを使用することが分かっている場合
(つまり、Win32 ではありません)、前の回答のコードから「シーク」を省略できます。

を実装する OS およびファイルシステム上で実行するコードのみを作成していることがわかっている場合
追加モード (最新の Unix 上のローカル ファイルシステムなど) が正しく設定されていれば、
ファイルをブロックバッファモードで作成し、各ファイルの間にバッファフルの出力を XNUMX つ未満書き込む場合
バッファを手動でフラッシュすると、各バッファロードはほぼ確実に書き込まれます。
他の人の出力と混ざらずに、ファイルの終わりを XNUMX つのチャンクにまとめます。
システムの単なるラッパーである「syswrite」関数を使用することもできます。
書きます(2)システムコール。

理論上、信号がシステムレベルのシステムを中断する可能性はまだわずかにあります。
完了前の「write()」操作。 一部の STDIO が問題になる可能性もあります。
実装では、バッファが空であっても複数のシステム レベルの「write()」を呼び出すことがあります。
始める。 この確率がゼロになるシステムもあるかもしれません。
システムの STDIO の代わりに「:perlio」を使用する場合は問題ありません。

認定条件 do I 無作為に update a バイナリ ファイル?
バイナリにパッチを適用したいだけの場合は、多くの場合、次のような単純な方法で機能します。

perl -i -pe '{ウィンドウマネージャー}{ウィンドウマングラー}g' /usr/bin/emacs

ただし、固定サイズのレコードがある場合は、次のようなことを行うこともできます。

私の$RECSIZE = 220; # レコードのサイズ (バイト単位)
私の $recno = 37; # どのレコードを更新するか
$fh、'+<'、'somewhere' を開くか、「どこかで更新できません: $!」;
$fh, $recno * $RECSIZE, 0; をシークします。
read $fh, $record, $RECSIZE == $RECSIZE or die "レコード $recno: $!" を読み取れません。
# レコードを書き換える
$fh、-$RECSIZE、1をシークします。
$fh $レコードを印刷します。
$fhを閉じます。

ロックとエラー チェックは、読者の演習として残されています。 それらを忘れないでください、あるいは
とても残念に思うでしょう。

認定条件 do I 取得する a ファイルの タイムスタンプ in パール?
ファイルが最後に読み取られた、書き込まれた、またはファイルが最後に保存された時刻を取得したい場合は、
メタデータ (所有者など) が変更された場合は、 -A, -Mまたは -C ファイルテスト操作として
perlfunc に文書化されています。 これらはファイルの経過時間を取得します (開始日と比較して測定)。
プログラムの時間) を浮動小数点数として日数で表します。 プラットフォームによってはすべてが揃っていない場合があります
この頃の。 詳細については、perlport を参照してください。 からの「生の」時間を秒単位で取得するには、
エポックでは、stat 関数を呼び出してから、「localtime()」、「gmtime()」、または
「POSIX::strftime()」を使用して、これを人間が読める形式に変換します。

次に例を示します。

私の $write_secs = (stat($file))[9];
printf "ファイル %s は %s に更新されました\n", $file,
スカラーローカルタイム($write_secs);

より読みやすいものが必要な場合は、File::stat モジュール (標準モジュールの一部) を使用してください。
バージョン 5.004 以降での配布):

# エラーチェックは読者のための演習として残されています。
ファイル::統計を使用します。
Time::localtime を使用します。
私の $date_string = ctime(stat($file)->mtime);
print "ファイル $file が $date_string に更新されました\n";

この POSIX::strftime() このアプローチには、理論的には、
現在のロケール。 詳細については、「perllocale」を参照してください。

認定条件 do I セッションに a ファイルの タイムスタンプ in パール?
あなたが使用 utime() perlfunc の「utime」に文書化された関数。 例として、次のとおりです
最初の引数からすべての引数に読み取りおよび書き込み時間をコピーする小さなプログラム
残りは。

if (@ARGV < 2) {
die "使用法: cptimes timestamp_file other_files ...\n";
}
私の $timestamp = シフト;
my($atime, $mtime) = (stat($timestamp))[8,9];
utime $atime、$mtime、@ARGV;

エラーチェックは、いつものように、読者の演習として残されています。

utime の perldoc にも、次と同じ効果を持つ例があります。 touch(1) ファイルについて
それ 既に 存在する.

特定のファイル システムでは、ファイルに予想どおりの時刻を保存する能力が限られています。
精度のレベル。 たとえば、FAT および HPFS ファイルシステムは日付を作成できません。
XNUMX 秒よりも細かい粒度のファイル。 これはファイルシステムの制限です。
ではない utime().

認定条件 do I 印刷 〜へ 他には? より XNUMXつ file at 一度?
XNUMX つのファイルハンドルを複数の出力ファイルハンドルに接続するには、IO::Tee または
Tie::FileHandle::Multiplex モジュール。

これを XNUMX 回だけ行う必要がある場合は、各ファイルハンドルに個別に出力できます。

私の $fh ($fh1, $fh2, $fh3) { print $fh "whatever\n" }

認定条件 できる I read in an 全体 file at 一度?
ファイル内のすべての行を処理する通常の Perl アプローチでは、次の時点で XNUMX 行ずつ処理します。
時間:

$input、'<'、$file を開くか、「$file を開けません: $!」を選択してください。
while (<$input>) {
ムシャムシャ。
# $_ で何かをする
}
$input を閉じるか死ぬか "$file: $! を閉じることができません。";

これは、ファイル全体を配列としてメモリに読み取るよりもはるかに効率的です。
行数を増やし、それを一度に XNUMX 要素ずつ処理します。これは、ほとんどではないにしても、多くの場合です。
常に、間違ったアプローチです。 誰かがこれをしているのを見ると、次のようになります。

私の @lines = ;

すべてを一度にロードする必要がある理由をじっくり考えてください。 ただそうではありません
スケーラブルなソリューション。

CPAN の File::Map モジュールを使用してファイルを「mmap」すると、仮想的にロードできます。
実際にメモリに保存せずに、ファイル全体を文字列に変換します。

ファイル::マップを使用する qw(マップファイル);

map_file 私の $string、$filename;

マップすると、$string を他の文字列と同様に扱うことができます。 あなたはそうしないので
必然的にデータをロードする必要があるため、mmap は非常に高速であるため、パフォーマンスが向上しない可能性があります。
メモリのフットプリント。

標準の Tie::File モジュールまたは DB_File を使用するとさらに楽しいかもしれません。
モジュールの $DB_RECNO バインディング。配列をファイルに結び付けることができるため、
配列の要素は実際にファイル内の対応する行にアクセスします。

ファイル全体をロードしたい場合は、Path::Tiny モジュールを使用して一度にロードできます。
シンプルで効率的な手順:

Path::Tiny を使用します。

私の $all_of_it = path($filename)->slurp; # スカラーのファイル全体
私の @all_lines = パス($filename)->行; # 要素ごとに XNUMX 行

または、次のようにファイルの内容全体をスカラーに読み取ることもできます。

私の$var;
{
ローカル $/;
$fh、'<'、$file を開くか、「$file を開けません: $!」を選択してください。
$var = <$fh>;
}

これにより、レコード区切り文字の定義が一時的に解除され、次の時点でファイルが自動的に閉じられます。
出口をブロックします。 ファイルがすでに開いている場合は、次のようにしてください。

my $var = do {ローカル $/; <$fh> };

ローカライズされた @ARGV を使用して「オープン」を排除することもできます。

my $var = do { local( @ARGV, $/ ) = $file; <> };

通常のファイルの場合は、「読み取り」機能も使用できます。

read( $fh, $var, -s $fh );

XNUMX 番目の引数は、$fh ファイルハンドル上のデータのバイト サイズをテストし、それを読み取ります。
多くのバイトがバッファ $var に格納されます。

認定条件 できる I read in a file by 段落?
$/ 変数を使用します (詳細については perlvar を参照してください)。 「」に設定して削除することもできます
空の段落 (たとえば、「abc\n\n\n\ndef」は XNUMX つの段落として扱われ、そうではありません)
XNUMX)、または「\n\n」を使用して空の段落を受け入れます。

空白行には空白を含めてはいけないことに注意してください。 したがって、「fred\n \nstuff\n\n」は XNUMX つです
段落ですが、「fred\n\nstuff\n\n」は XNUMX つです。

認定条件 できる I read a 文字 から a ファイル?   キーボード?
ほとんどのファイルハンドルには組み込みの「getc()」関数を使用できますが、(簡単には)機能しません。
端末デバイス上で。 STDIN の場合は、CPAN の Term::ReadKey モジュールを使用するか、
perlfunc の「getc」にあるサンプルコード。

システムがポータブル オペレーティング システム プログラミング インターフェイス (POSIX) をサポートしている場合は、
次のコードを使用すると、エコー処理もオフになることがわかります。

#!/ usr / bin / perl -w
厳格な使用;
$| = 1;
(1..4) {の場合
print "gimme: ";
私の $got = getone();
print "--> $got\n";
}
出口;

ベギン {
POSIX qw(:termios_h) を使用します。

私の ($term、$oterm、$echo、$noecho、$fd_stdin);

私の$fd_stdin = ファイル番号(STDIN);

$term = POSIX::Termios->new();
$term->getattr($fd_stdin);
$oterm = $term->getlflag();

$エコー = エコー | エチョック | イカノン。
$noecho = $oterm & ~$echo;

サブブレーク {
$term->setlflag($noecho);
$term->setcc(VTIME, 1);
$term->setattr($fd_stdin, TCSANOW);
}

サブ調理済み{
$term->setlflag($oterm);
$term->setcc(VTIME, 0);
$term->setattr($fd_stdin, TCSANOW);
}

サブ getone {
私の $key = '';
cbreak();
sysread(STDIN, $key, 1);
調理済み();
$key を返します。
}
}

END {調理済み() }

CPAN の Term::ReadKey モジュールの方が使いやすいかもしれません。 最近のバージョンには次のものが含まれます
非ポータブル システムもサポートします。

Term::ReadKey を使用します。
$tty、'<'、'/dev/tty' を開きます。
print "文字をください: ";
ReadMode "生";
私の $key = ReadKey 0, $tty;
ReadMode「通常」;
printf "\nあなたは %s、文字番号 %03d と言った\n",
$key、または $key;

認定条件 できる I 言う かどうか あります a 文字 待ち望ん on a ファイルハンドル?
まず最初に行うべきことは、Term::ReadKey 拡張機能を次から取得することです。
CPAN。 前に述べたように、現在は非ポータブルのサポートも限定的になっています (つまり、
オープン システム、クローズド システム、プロプライエタリ システム、POSIX ではない、Unix ではないなど)システム。

comp.unix.* のよくある質問リストも確認してください。
このように、答えは本質的に同じです。 それはシステムに大きく依存します。 ここに XNUMX つあります
BSD システムで動作するソリューション:

サブキー_準備完了 {
my($rin, $nfd);
vec($rin, ファイル番号(STDIN), 1) = 1;
return $nfd = select($rin,undef,undef,0);
}

待機している文字数を知りたい場合は、FIONREAD ioctl もあります。
見てもらうように呼びかけます。 の 時2時 Perl に付属のツールは C インクルード ファイルを変換しようとします
Perl コードに変換します。これは「必須」にすることができます。 FIONREAD は最終的に次の関数として定義されます。
sys/ioctl.ph ファイル:

「sys/ioctl.ph」が必要です。

$size = パック("L", 0);
ioctl(FH, FIONREAD(), $size) または die "ioctl を呼び出すことができませんでした: $!\n";
$size = unpack("L", $size);

If 時2時 インストールされていないか、機能しない場合は、 grep インクルード ファイルを手動で作成します。

% grep FIONREAD / usr / include /* / *
/usr/include/asm/ioctls.h:#define FIONREAD 0x541B

または、チャンピオンのエディターを使用して小さな C プログラムを作成します。

% 猫 > fionread.c
#含む
主要() {
printf("%#08x\n", FIONREAD);
}
^D
% cc -o fionread fionread.c
% ./fionread
0x4004667f

そして、それをハードコーディングし、移植を後任者の演習として残します。

$FIONREAD = 0x4004667f; # XXX: オプシスに依存します

$size = パック("L", 0);
ioctl(FH, $FIONREAD, $size) または die "ioctl を呼び出せませんでした: $!\n";
$size = unpack("L", $size);

FIONREAD では、ストリームに接続されたファイルハンドルが必要です。つまり、ソケット、パイプ、および tty
デバイスは動作しますが、 ファイル。

認定条件 do I do a "しっぽ -f" in パール?
初挑戦

シーク($gw_fh, 0, 1);

「seek($gw_fh, 0, 1)」ステートメントは現在位置を変更しませんが、クリアします。
ハンドルのファイル終了条件。次の "<$gw_fh>" で Perl が再試行されます。
何かを読むこと。

それが機能しない場合 (stdio 実装の機能に依存する場合)、次のことが必要です。
もっとこんな感じ:

のために(;;) {
for ($curpos = Tell($gw_fh); <$gw_fh>; $curpos =tell($gw_fh)) {
# 何かを検索してファイルに入れる
}
#ちょっと寝よう
シーク($gw_fh, $curpos, 0); # 私たちがいた場所を探す
}

これでもうまくいかない場合は、IO::Handle の「clearerr」メソッドを調べてください。
ハンドルのエラーとファイルの終わりの状態。

CPAN の File::Tail モジュールもあります。

認定条件 do I dup() a ファイルハンドル in Perl?
perlfunc で「open」をチェックすると、いくつかの呼び出し方法が表示されることがわかります。 開いた() すべき
トリックをやってください。 例えば:

$log、'>>'、'/foo/logfile' を開きます。
STDERR、'>&'、$log を開きます。

または、リテラル数値記述子を使用しても:

私の $fd = $ENV{MHCONTEXTFD};
$mhcontext を開きます、"<&=$fd"; # のように fdopen(3S)

「<&STDIN」はコピーを作成しますが、「<&=STDIN」はエイリアスを作成することに注意してください。 つまり、閉じてしまうと、
別名ハンドルを使用すると、すべての別名にアクセスできなくなります。 コピーされたものには当てはまりません。

いつものように、エラー チェックは読者の演習として残されています。

認定条件 do I 閉じる a file ディスクリプタ by 数?
何らかの理由で、ファイルハンドルの代わりにファイル記述子がある場合 (おそらく、
"POSIX::open")、POSIX モジュールの "close()" 関数を使用できます。

POSIX () を使用します。

POSIX::close( $fd );

Perl の「close()」関数は何かに使用されるため、これが必要になることはほとんどありません。
「MHCONTEXT」のような数値記述子の複製であっても、Perl 自体が開かれたこと
その上。 しかし、どうしても必要な場合は、次のことができるかもしれません。

「sys/syscall.ph」が必要です。
私の $rc = syscall(SYS_close(), $fd + 0); # 数値を強制する必要があります
die "$fd: $を sysclose できません!" $rc == -1 でない場合;

または、 fdopen「open()」の(3S)機能:

{
$fh を開くか、"<&=$fd" か、死ぬか "fd=$fd を再度開くことができません: $!";
$fhを閉じます。
}

なぜ することはできません I つかいます 「C:\temp\foo」 in DOS パス? なぜ しない `C:\temp\foo.exe` 動作しますか?
おっと! そのファイル名にタブとフォームフィードを挿入するだけです。 内にあることを覚えておいてください
二重引用符で囲まれた文字列 (「like\this」)、バックスラッシュはエスケープ文字です。 完全なリスト
これらのうちの XNUMX つは、perlop の「引用符と引用文のような演算子」にあります。 当然のことながら、あなたは持っていません
従来の DOS では「c:(tab)emp(formfeed)oo」または「c:(tab)emp(formfeed)oo.exe」というファイル
ファイルシステム。

文字列を一重引用符で囲むか、(できれば) スラッシュを使用します。 すべての DOS と
MS-DOS 2.0 以降の Windows バージョンでは、「/」と「\」は同じように扱われます。
パスでは、Perl または POSIX シェルと衝突しないものを使用することもできます。
ほんの数例を挙げると、ANSI C および C++、awk、Tcl、Java、Python などです。 POSIX パスはさらに多くなります
ポータブルも。

なぜ しない glob("*.*") 取得する   ファイル?
Unix 以外のポートでも、Perl の glob 関数は標準の Unix グロビングに従うためです。
セマンティクス。 すべての (非表示でない) ファイルを取得するには、「glob("*")」が必要です。 これにより、 glob()
レガシー システムにも移植可能です。 ポートには独自のグロビング関数が含まれている場合があります。
良い。 詳細については、ドキュメントを確認してください。

なぜ ありません パール me 削除 読み取り専用の ファイル? なぜ ありません "-私" 強盗 保護された ファイル? そうではない この
a バグ in Perl?
これについては、詳しく、丹念に説明されています。 ファイルディレクトリパーマ 「遠い」の記事
「More Than You Ever Wanted To Know」コレクション
<http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz>。

要旨: ファイルシステムがどのように機能するかを学びましょう。 ファイルのパーミッションは何を表しますか
そのファイル内のデータに問題が発生する可能性があります。 ディレクトリの権限は、何が起こるかを示します
そのディレクトリ内のファイルのリストに。 ファイルを削除すると、その名前も削除されます
ディレクトリから (したがって、操作はディレクトリの権限ではなく、ディレクトリの権限に依存します)
ファイル)。 ファイルに書き込もうとすると、ファイルのアクセス許可によって、
あなたには許可されています。

認定条件 do I select a ランダム ライン から a ファイル?
ファイルをデータベースにロードしたり、ファイル内の行に事前にインデックスを付けたりする以外には、次のような方法があります。
あなたができることがいくつかあります。

以下は Camel Book の貯留層サンプリング アルゴリズムです。

スランド;
rand($.) < 1 && ($line = $_) while <>;

これには、ファイル全体を読み取るよりもスペースの面で大きな利点があります。
この方法の証明 この 宝品 of パソコン プログラミング、第 2 巻、セクション 3.4.2、作成者
ドナルド・E・クヌース

そのアルゴリズムの関数を提供する File::Random モジュールを使用できます。

ファイル::ランダム qw/random_line/ を使用します。
私の $line = ランダムライン($ファイル名);

もう XNUMX つの方法は、ファイル全体を配列として扱う Tie::File モジュールを使用することです。
ランダムな配列要素にアクセスするだけです。

なぜ do I 取得する 奇妙な スペース いつ I 印刷 an 配列 of 線?
(ブライアン・ド・フォイによる寄稿)

配列を印刷するときに配列の要素間にスペースが表示される場合は、
おそらく配列を二重引用符で囲んで補間していると思われます。

私の @animals = qw(ラクダ ラマ アルパカ ビキューナ);
print "動物は: @animals\n";

これを行うのは「印刷」ではなく、二重引用符です。 配列を補間するたびに、
二重引用符コンテキストの場合、Perl は要素をスペース (または $" にあるもの) で結合します。
デフォルトではスペースです):

動物は次のとおりです: ラクダ ラマ アルパカ ビキューナ

これは、補間なしで配列を出力するのとは異なります。

私の @animals = qw(ラクダ ラマ アルパカ ビキューナ);
print "動物は次のとおりです: ", @animals, "\n";

現在、出力には要素間にスペースがありません。
@animals は単に「印刷」するリストの一部になります。

動物は次のとおりです: カメッラマアルパカヴィクナ

@array の各要素が改行で終わっているときにこれに気づくかもしれません。 あなたは期待しています
XNUMX 行に XNUMX つの要素を出力しますが、最初の行以降のすべての行がインデントされていることに注意してください。

これは行です
これは別の行です
これはXNUMX行目です

この余分なスペースは、配列の補間によって得られます。 入れたくない場合は
配列要素の間に何かを配置する場合は、配列を二重引用符で囲んで使用しないでください。 送信できます
それらを使用せずに印刷するには:

@line を印刷します。

認定条件 do I トラバース a ディレクトリにジョブを開始します。 木?
(ブライアン・ド・フォイによる寄稿)

Perl に付属する File::Find モジュールは、ファイルを走査するためのすべてのハードワークを実行します。
ディレクトリ構造。 Perl が付属しています。 次のコマンドを使用して「find」サブルーチンを呼び出すだけです。
コールバック サブルーチンとトラバースするディレクトリ:

File :: Findを使用します。

find( \&wanted, @directories );

サブ募集中{
# $File::Find::name のフルパス
# $_ にはファイル名のみ
...やりたいことは何でもやってください...
}

CPAN からダウンロードできる File::Find::Closures には、すぐに使用できる機能が多数用意されています。
File::Find で使用できるサブルーチン。

CPAN からダウンロードできる File::Finder は、コールバックの作成に役立ちます。
「find」コマンドライン ユーティリティの構文に近いものを使用するサブルーチン:

File :: Findを使用します。
File::Finder を使用します。

my $deep_dirs = File::Finder-> Depth->type('d')->ls->exec('rmdir','{}');

find( $deep_dirs->as_options, @places );

CPAN からダウンロードできる File::Find::Rule モジュールには同様のインターフェイスがあります。
しかし、あなたのためにも走査を行います:

File :: Find :: Ruleを使用します。

私の @files = File::Find::Rule->file()
->名前( '*.pm' )
->in( @INC );

認定条件 do I 削除 a ディレクトリにジョブを開始します。 木?
(ブライアン・ド・フォイによる寄稿)

空のディレクトリがある場合は、Perl の組み込みの「rmdir」を使用できます。 ディレクトリが
空ではない(つまり、ファイルやサブディレクトリがない)場合は、自分で空にする必要があります(多くの場合、
work) するか、役立つモジュールを使用してください。

Perl に付属する File::Path モジュールには、次の処理を行うことができる「remove_tree」があります。
すべての苦労はあなたのためにあります:

ファイル::パスを使用します。 qw(remove_tree);

削除_ツリー( @ディレクトリ );

File::Path モジュールには、古い「rmtree」サブルーチンへのレガシー インターフェイスもあります。

認定条件 do I copy an 全体 ディレクトリ?
(Shlomi Fish による寄稿)

「cp -R」と同等のことを実行するには (つまり、ディレクトリ ツリー全体を再帰的にコピーします)
ポータブルな Perl では、自分で何かを書くか、適切な CPAN モジュールを見つける必要があります。
ファイル::コピー::再帰など。

著者 そして COPYRIGHT


Copyright(c)1997-2010 Tom Christiansen、Nathan Torkington、およびその他の著者。
All rights reserved.

このドキュメントは無料です。 同じ条件で再配布および/または変更できます
Perl自体として。

その配布に関係なく、ここでのすべてのコード例はパブリックドメインにあります。 あなたは
このコードとその派生物を独自のプログラムで使用することを許可および推奨します
あなたが適切だと思うように、楽しみのために、または利益のために。 にクレジットを与えるコード内の簡単なコメント
FAQは丁寧ですが、必須ではありません。

onworks.netサービスを使用してperlfaq5をオンラインで使用する


無料のサーバーとワークステーション

Windows と Linux のアプリをダウンロード

Linuxコマンド

Ad