2010-09-12 39 views
8

Đây là những gì mã Perl của tôi trông giống như cho monitoring a Unix folder:Chúng ta có một autochomp trong 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; 
} 
  • Để làm một chomp sau mỗi lần chuyển nhượng không nhìn tốt. Có cách nào để làm một "autochomp"?

  • Tôi mới sử dụng Perl và có thể không viết mã này theo cách tốt nhất. Bất kỳ đề xuất nào để cải thiện mã đều được chào đón.

+1

Bạn cũng nên nhớ rằng 'chomp' có thể lấy một danh sách:' chomp ($ foo, $ bar, $ fubb) '. – FMc

Trả lời

14

Don 't sử dụng vỏ, sau đó.

#! /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; 

Kết quả là hơi khác nhau: đầu ra của lệnh date chứa một múi giờ, nhưng giá trị của $date trên sẽ không. Nếu đây là sự cố, hãy làm theo đề xuất tuyệt vời bằng cách Chas. Owens bên dưới và sử dụng strftime để nhận định dạng bạn muốn.

tiểu của bạn

sub touchandmail { 
    `touch $cache -t "$datef"`; 
    `echo "$msg" | mail -s "$subject" $owner -c $sendto`; 
} 

sẽ thất bại âm thầm nếu họ gặp khó khăn. Im lặng thất bại là khó chịu. Tốt hơn sẽ là mã dọc theo dòng của

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: $!"; 
    } 
    } 
} 

Sử dụng system hơn backticks là biểu cảm hơn về ý định của mình vì backticks là để chụp đầu ra. Biểu mẫu system(LIST) bỏ qua trình bao và phải lo lắng về việc trích dẫn đối số.

Lấy hiệu ứng của đường ống vỏ echo ... | mail ... mà không có vỏ có nghĩa là chúng ta phải làm một chút công việc hệ thống ống nước, nhưng lợi ích — như với system(LIST) —không phải lo lắng về việc trích dẫn vỏ. Đoạn mã trên sử dụng nhiều đối số open:

Đối với ba hoặc nhiều đối số nếu THỨC là '|-', tên tập tin được hiểu như là một lệnh mà đầu ra là để được cấp nước tập trung, và nếu chế độ là '-|', tên tập tin được giải thích như một lệnh mà đầu ra ống cho chúng tôi.Trong biểu mẫu hai đối số (và một đối số), bạn nên thay thế dấu gạch ngang ('-') bằng lệnh. Xem Using open for IPC in perlipc để biết thêm ví dụ về điều này.

open trên dĩa ở trên mail$fh được kết nối với đầu vào tiêu chuẩn. Quy trình gốc (mã vẫn chạy touchandmail) thực hiện vai trò là echo với print $fh $msg. Gọi close bừng của cán bộ đệm O I/cộng thêm một chút vì cách chúng tôi mở nó ra:

Nếu filehandle xuất thân từ một đường ống open, close lợi nhuận false nếu một trong những syscalls khác liên quan đến thất bại hoặc nếu chương trình của mình thoát với trạng thái khác 0. Nếu vấn đề duy nhất là chương trình đã thoát không khác, $! sẽ được đặt thành 0. Đóng một đường ống cũng đợi quá trình thực thi trên đường ống để thoát - trong trường hợp bạn muốn xem đầu ra của ống sau đó — và ngầm đặt giá trị trạng thái thoát của lệnh đó vào $?${^CHILD_ERROR_NATIVE}.

+0

cảm ơn các gợi ý touchandmail. Tôi đã nghĩ đến việc kết hợp một số lỗi xử lý cho nó. – Lazer

+0

"' - | "là gì? – Lazer

+0

@Lazer: '| -' mở một đường ống và chuyển hướng tất cả mọi thứ được ghi vào tập tin tới stdin của quy trình mới. –

5

Cố gắng đưa nó vào một hàm:

sub autochomp { 
    my $command = shift; 
    my $retval = `$command`; 
    chomp $retval; 
    return $retval; 
} 

Và sau đó gọi rằng đối với mỗi lệnh bạn muốn thực hiện và sau đó nhai.

4

Sử dụng DateTime hoặc các mô-đun ngày khác trên CPAN thay vì tiện ích ngày.

Ví dụ:

use DateTime; 

my $dt = DateTime->now; 
print $dt->strftime('%Y%m%d%H%M.%S'); 
+1

Chỉ với ngày 'POSIX' có khả năng dễ dàng hơn/nhẹ hơn:' sử dụng POSIX qw/strftime /; $ date = strftime của tôi "% Y% m% d% H% M.% S", giờ địa phương; ' – Telemachus

2

Có thể gán và chomp trong một dòng duy nhất bằng cách sử dụng cú pháp sau:

chomp (my $date = `date`); 

Đối với nói nhiều Perlishly, nếu bạn thấy mình lặp lại giống nhau điều này lặp đi lặp lại, cuộn nó vào một phụ:

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`); 
+0

[' chomp'] (http://perldoc.perl.org/functions/chomp.html) "trả về tổng số ký tự bị xóa khỏi tất cả các đối số của nó, "không phải là kết quả bị chomped. –

+0

@gbacon: Đó là lý do tại sao tôi 'chomp' scalars từng cái một – Zaid

+1

Nhưng vòng lặp của bạn đẩy giá trị được trả về từ' chomp' vào '@ result'. –

6

Tổng quát hơn, các mô-đun IO::All không thực sự cung cấp tương đương với một autochomp:

use IO::All; 
# for getting command output: 
my @date = io("date|")->chomp->slurp; 
#$date[0] contains the chomped first line of the output 

hoặc tổng quát hơn:

my $fh = io("file")->chomp->tie; 
while (<$fh>) { 
# no need to chomp here ! $_ is pre-chomped 
} 

Cấp, đối với trường hợp đặc biệt này của date tôi sẽ đồng ý với những người trả lời khác rằng bạn có thể sử dụng một trong các mô-đun DateTime tốt hơn, nhưng nếu bạn chỉ đọc một tệp và muốn tất cả các dòng của mình là chomp ed, sau đó IO::All với các tùy chọn chomptie được áp dụng rất thuận tiện.

Lưu ý rằng thủ thuật chomp không hoạt động khi rót toàn bộ nội dung của tay cầm vào vô hướng trực tiếp (đó chỉ là cách nó được triển khai).

Các vấn đề liên quan