/ / Perlに自動選択機能はありますか? --perl、string、chomp

Perlにオートチョップはありますか? -perl、string、chomp

これは私の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つを使用したほうがよいと思いますが、単にファイルを読み込んでいて、すべての行を chomped、その後 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` );