これは私のPerlコードがどのように見えるかです Unixフォルダの監視 :
#!/usr/bin/perl
use strict;
use warnings;
use File::Spec::Functions;
my $date = `date`; chomp $date;
my $datef = `date +%Y%m%d%H%M.%S`; chomp $datef;
my $pwd = `pwd`; chomp $pwd;
my $cache = catfile($pwd, "cache");
my $monitor = catfile($pwd, "monme");
my $subject = "...";
my $msg = "...";
my $sendto = "...";
my $owner = "...";
sub touchandmail {
`touch $cache -t "$datef"`;
`echo "$msg" | mail -s "$subject" $owner -c $sendto`;
}
while(1) {
$date = `date`; chomp $date;
$datef = `date +%Y%m%d%H%M.%S`; chomp $datef;
if (! -e "$cache") {
touchandmail();
} elsif ("`find $monitor -newer $cache`" ne "") {
touchandmail();
}
sleep 300;
}
するために
chomp
すべての割り当てが良く見えない後。 「オートチョップ」を行う方法はありますか?私はPerlを初めて使用するので、このコードを最善の方法で記述していない可能性があります。コードを改善するための提案は大歓迎です。
回答:
回答№1は14その場合、シェルを使用しないでください。
#! /usr/bin/perl
use warnings;
use strict;
use Cwd;
use POSIX qw/ strftime /;
my $date = localtime;
my $datef = strftime "%Y%m%d%H%M.%S", localtime;
my $pwd = getcwd;
結果はわずかに異なります:の出力 date
コマンドにはタイムゾーンが含まれていますが、 $date
上記はしません。これが問題である場合は、次の優れた提案に従ってください。 チャス。オーエンス 以下を使用して strftime
必要な形式を取得します。
あなたの潜水艦
sub touchandmail {
`touch $cache -t "$datef"`;
`echo "$msg" | mail -s "$subject" $owner -c $sendto`;
}
何か問題が発生した場合、サイレントに失敗します。サイレント障害は厄介です。の行に沿ったコードの方が良いでしょう
sub touchandmail {
system("touch", "-t", $datef, $cache) == 0
or die "$0: touch exited " . ($? >> 8);
open my $fh, "|-", "mail", "-s", $subject, $owner, "-c", $sendto
or die "$0: could not start mail: $!";
print $fh $msg
or warn "$0: print: $!";
unless (close $fh) {
if ($! == 0) {
die "$0: mail exited " . ($? >> 8);
}
else {
die "$0: close: $!";
}
}
}
使用 system
バックティックは出力をキャプチャするためのものであるため、バックティックではなく、意図をより表現することができます。ザ・ system(LIST)
フォームはシェルをバイパスし、引数の引用について心配する必要があります。
シェルパイプラインの効果を得る echo ... | mail ...
シェルがないということは、自分で配管作業を少し行う必要があることを意味しますが、メリットは system(LIST)
—シェルの引用について心配する必要はありません。上記のコードは多くの引数を使用しています open
:
MODEがの場合、3つ以上の引数の場合
"|-"
、ファイル名は、出力がパイプされるコマンドとして解釈されます。MODEが"-|"
、ファイル名は、出力をパイプで送信するコマンドとして解釈されます。 2つの引数(および1つの引数)の形式では、ダッシュ("-"
)コマンドを使用します。見る 使用open
perlipcのIPC用 この他の例については。
ザ open
上記のフォーク mail
プロセス、および $fh
標準入力に接続されています。親プロセス(コードはまだ実行中です touchandmail
)の役割を果たします echo
〜と print $fh $msg
。呼び出し close
ハンドルのI / Oバッファに加えて、開いた方法のために少し余分なものをフラッシュします。
ファイルハンドルがパイプからのものである場合
open
,close
関連する他のシステムコールの1つが失敗した場合、またはそのプログラムがゼロ以外のステータスで終了した場合は、falseを返します。唯一の問題がプログラムがゼロ以外で終了したことであった場合、$!
0に設定されます。 パイプを閉じると、パイプで実行されているプロセスが終了するのを待ち(後でパイプの出力を確認したい場合)、そのコマンドの終了ステータス値を暗黙的に$?
そして${^CHILD_ERROR_NATIVE}
.
回答№2の6
より一般的には、 IO::All
モジュールは確かにautochompと同等のものを提供します:
use IO::All;
# for getting command output:
my @date = io("date|")->chomp->slurp;
#$date[0] contains the chomped first line of the output
もっと一般的には:
my $fh = io("file")->chomp->tie;
while (<$fh>) {
# no need to chomp here ! $_ is pre-chomped
}
確かに、この特定のケースでは date
他の回答者には、DateTimeモジュールの1つを使用したほうがよいと思いますが、単にファイルを読み込んでいて、すべての行を chomp
ed、その後 IO::All
とともに chomp
そして tie
適用されるオプションは非常に便利です。
また、 chomp
ハンドルの内容全体をスカラーに直接スカラーする場合、トリックは機能しません(これは実装方法です)。
回答№3のための5
関数に入れてみてください:
sub autochomp {
my $command = shift;
my $retval = `$command`;
chomp $retval;
return $retval;
}
次に、実行するコマンドごとにそれを呼び出してから、チョップします。
回答№4の4
日付ユーティリティの代わりに、CPANでDateTimeまたはその他の日付モジュールを使用します。
例えば:
use DateTime;
my $dt = DateTime->now;
print $dt->strftime("%Y%m%d%H%M.%S");
回答№5の2
を割り当てることが可能です chomp
次の構文を使用して1行で:
chomp ( my $date = `date` );
もっとPerlishlyに話すことに関しては、同じことを何度も繰り返していることに気付いた場合は、それをサブにロールバックします。
sub assign_and_chomp {
my @result;
foreach my $cmd (@_) {
chomp ( my $chomped = $cmd );
push @result, $chomped;
}
return @result;
}
my ( $date , $datef , $pwd )
= assign_and_chomp ( `date` , `date +%Y%m%d%H%M.%S` , `pwd` );