STDINがあるかどうかをテストしていると思った場所にコードを書きました。しかし、コードは私が期待していたものとは逆に機能しました。
これが私が書いたコードです、私はそれを呼んでいます zit
#!/usr/bin/perl
use strict 'vars';
my @a = @ARGV ? @ARGV : "EMPTY";
printf " command line arguments: \"%s\" as expected\n", @a;
if ( -t STDIN )
{
print " ( -t STDIN ) returns TRUE\n";
}
else
{
print " ( -t STDIN ) returns FALSE\n";
print " But, I can iterate over <STDIN>! Huh?? Behold:\n";
}
これが私が思ったことです:
zit <(echo a;echo b)
結果( -t STDIN )
としてFALSE
。
zit < <(echo a;echo b)
結果( -t STDIN )
としてTRUE
。
そこで、何が起こっているのかを理解するために、ループをif-then
追加してコードを変更しましたwhile
(私の理解に基づいて、問題が発生するはずの場所に配置しました)。
#!/usr/bin/perl
use strict 'vars';
my @a = @ARGV ? @ARGV : "EMPTY";
printf " command line arguments: \"%s\" as expected\n", @a;
if ( -t STDIN )
{
print " ( -t STDIN ) returns TRUE\n";
}
else
{
print " ( -t STDIN ) returns FALSE\n";
print " But, I can iterate over <STDIN>! Huh?? Behold:\n";
while ( <STDIN> )
{
print ">> $_";
}
}
これがこのコードからの出力です
zit <(echo a;echo b)
次の出力があります
command line arguments: "/dev/fd/63" as expected
( -t STDIN ) returns TRUE
zit < <(echo a;echo b)
次の出力があります
command line arguments: "EMPTY" as expected
( -t STDIN ) returns FALSE
But, I can iterate over <STDIN>! Huh?? Behold:
>> a
>> b
私はこれに本当に混乱しています。これは、私が思っていたように動作していません。( -t STDIN )
falseの場合、while
ループが機能するのはなぜですか?
誰かがここで何が起こっているのか説明できますか?
少し混乱を少なくするために、以前からこの投稿を再編集しました。
use strict 'vars';
なぜあなたはこれをやっている?だけuse strict;
でなく、3つの制限すべてを有効にする必要がありvars
ます。また、する必要がありuse warnings;
ます。
チェックするperldoc -f -t
と、ドキュメントに次のように記載されていることがわかります。
-t Filehandle is opened to a tty.
言い換えると、STDINがあるかどうかをテストするのではなく(親プロセスがいたずらで、開始する前に閉じた場合を除いて、常にSTDINがあります)、STDINが端末を参照しているかどうかをテストします(略称「tty」は元々参照されていました)。テレタイプ、彼らが置き換えられたスタックの名前の種類テキスト端末以降の端末エミュレータxtermのような)。C用語では、への呼び出しに対応しますisatty
。
最初の例では、がありzit <(echo a;echo b)
ます。この<( ... )
表記により、bashは指定されたコマンドを実行し、STDOUTをパイプにリダイレクトします。次に<( ... )
、パイプ(の読み取り側)を参照するファイル名に置き換えます。
具体的には、実行されますzit /dev/fd/63
(ファイル記述子63は、書き込み端がによって供給されるパイプの読み取り端を指しますecho a; echo b
)。STDINには何も起こらないためzit
、シェルから標準ストリームを継承します。したがって、STDINは端末を参照し-t STDIN
ます。これが、trueを返す理由です。
2番目の例では、がありzit < <(echo a;echo b)
ます。これは非常に似ていますが、結果のコマンドはzit < /dev/fd/63
です。この< FILE
表記は、指定されたファイルを読み取り用に開き、STDINをそのファイルにリダイレクトするようにシェルに指示します。
したがってzit
、STDINがパイプに接続された状態で(コマンドライン引数なしで)実行されます(パイプのもう一方の端はによって供給されますecho a; echo b
)。これは事実上と同じ( echo a; echo b ) | zit
です。ここで、zitのSTDINは端末ではなくパイプを参照しているため、-t STDIN
falseを返します。もちろん、それでも読み取ることができます。読み取ることができるもののほとんどは、プレーンファイル、パイプ、ソケットなどの端末ではありません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加