perl - 我们在Perl中有自动冠军吗?

标签 perl string chomp

这是monitoring a Unix folder的Perl代码的样子:

#!/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的新手,可能没有以最佳方式编写此代码。欢迎提供任何改进代码的建议。
  • 最佳答案

    那不要使用 shell 。

    #! /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的值不会。如果存在问题,请遵循下面Chas. Owens的出色建议,并使用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)表单绕过 shell 程序,不必担心引用参数。

    在没有 shell 的情况下获得 shell 管道echo ... | mail ...的效果意味着我们必须自己做一些管道工作,但是与system(LIST)一样,这样做的好处是不必担心 shell 引用。上面的代码使用多参数 open :

    For three or more arguments if MODE is '|-', the filename is interpreted as a command to which output is to be piped, and if MODE is '-|', the filename is interpreted as a command that pipes output to us. In the two-argument (and one-argument) form, one should replace dash ('-') with the command. See Using open for IPC in perlipc for more examples of this.



    上面的open派生了一个mail进程,并且$fh连接到其标准输入。父进程(代码仍在运行touchandmail)与echo一起扮演print $fh $msg的角色。调用 close 会刷新句柄的I/O缓冲区以及一些额外的内容,这是因为我们如何打开它的:

    If the filehandle came from a piped open, close returns false if one of the other syscalls involved fails or if its program exits with non-zero status. If the only problem was that the program exited non-zero, $! will be set to 0. Closing a pipe also waits for the process executing on the pipe to exit—in case you wish to look at the output of the pipe afterwards—and implicitly puts the exit status value of that command into $? and ${^CHILD_ERROR_NATIVE}.

    关于perl - 我们在Perl中有自动冠军吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3694465/

    相关文章:

    perl - 如何为HTML编码字符串?

    perl - Perl 中的 "Use of uninitialized value in scalar chomp"

    perl - perl 表达式 $a = $a++ 中是否有任何副作用?

    oracle - 如何在 perl 脚本中使用 IPC::Run 模块

    java - JRuby:从 RubyString 创建 Java InputStream 或 byte[]

    c++ - 代码输出随机符号,我不确定出了什么问题

    c# - 逗号分隔字符串的对象

    perl - 使用 chomp() 时打印失败

    ruby - 我怎样才能一次压缩数组中的每一行?

    perl - ubuntu apache2 cgi 输出缓冲