3

我有一个包含包含的 Perl 脚本

open (FILE, '<', "$ARGV[0]") || die "Unable to open $ARGV[0]\n";

while (defined (my $line = <FILE>)) {
  # do stuff
}

close FILE;

我想.pp在目录中的所有文件上运行这个脚本,所以我在 Bash 中编写了一个包装脚本

#!/bin/bash
for f in /etc/puppet/nodes/*.pp; do
    /etc/puppet/nodes/brackets.pl $f
done

问题

是否可以避免使用包装脚本并让 Perl 脚本来代替它?

4

7 回答 7

8

是的。

翻译for f in ...;成 Perl

  • for my $f (...) { ... }(在列表的情况下)或
  • while (my $f = ...) { ... }(在迭代器的情况下)。

您使用的 glob 表达式 ( /etc/puppet/nodes/*.pp) 可以在 Perl 中通过glob函数:求值glob '/etc/puppet/nodes/*.pp'

连同一些样式改进:

use strict; use warnings;
use autodie;  # automatic error handling

while (defined(my $file = glob '/etc/puppet/nodes/*.pp')) {
  open my $fh, "<", $file;  # lexical file handles, automatic error handling

  while (defined( my $line = <$fh> )) {
    do stuff;
  }
  close $fh;
}

然后:

$ /etc/puppet/nodes/brackets.pl
于 2013-08-15T12:56:14.227 回答
6

这不是您所要求的,但另一种可能性是使用<>

while (<>) {
    my $line = $_;
    # do stuff
}

然后将文件名放在命令行上,如下所示:

/etc/puppet/nodes/brackets.pl /etc/puppet/nodes/*.pp

Perl 为您打开和关闭每个文件。(在循环内,当前文件名和行号分别是$ARGV$.。)

于 2013-08-15T12:53:58.380 回答
2

Jason Orendorff有正确的答案:

来自Perlop(I/O 操作员)

空文件句柄 <> 是特殊的:它可以用来模拟 sed 和 awk 的行为,以及任何其他接受文件名列表的 Unix 过滤程序,对来自所有文件名的每一行输入执行相同的操作。<> 的输入要么来自标准输入,要么来自命令行中列出的每个文件。

这不需要opendir. 它不需要globs在您的程序中使用或硬编码的东西。这是读取在命令行中找到的所有文件或从 STDIN 通过管道传输到程序中的所有文件的自然方式。

有了这个,你可以这样做:

$ myprog.pl /etc/puppet/nodes/*.pp

或者

$ myprog.pl /etc/puppet/nodes/*.pp.backup

甚至:

$ cat /etc/puppet/nodes/*.pp | myprog.pl
于 2013-08-15T15:51:38.540 回答
1

我建议将所有文件名放入数组,然后将此数组用作 perl 方法或脚本的参数列表。请看以下代码:

use Data::Dumper
$dirname = "/etc/puppet/nodes";
opendir ( DIR, $dirname ) || die "Error in opening dir $dirname\n";

my @files = grep {/.*\.pp/} readdir(DIR);
print Dumper(@files);

closedir(DIR);

现在您可以将 \@files 作为参数传递给任何 perl 方法。

于 2013-08-15T12:59:07.323 回答
1

看看这个文档,它解释了你需要知道的一切

#!/usr/bin/perl

use strict;
use warnings;

my $dir = '/tmp';

opendir(DIR, $dir) or die $!;

while (my $file = readdir(DIR)) {
# We only want files
next unless (-f "$dir/$file");

# Use a regular expression to find files ending in .pp


   next unless ($file =~ m/\.pp$/);
open (FILE, '<', $file) || die "Unable to open $file\n";

while (defined (my $line = <FILE>)) {
  # do stuff
}
}

closedir(DIR);
exit 0;
于 2013-08-15T12:46:59.303 回答
0
   my @x =   <*>;  

   foreach ( @x ) {
      chomp;
      if ( -f "$_" ) {
         print "process $_\n";  
         # do stuff
         next;
      };

    };
于 2013-08-15T19:45:03.140 回答
-2

Perl 可以通过各种方式执行系统命令,最直接的是使用反引号 ``

use strict;
use warnings FATAL => 'all';

my @ls = `ls /etc/puppet/nodes/*.pp`;
for my $f ( @ls ) {
   open (my $FILE, '<', $f) || die "Unable to open $f\n";

   while (defined (my $line = <$FILE>)) {
      # do stuff
   }
   close $FILE;
}

(注意:你应该总是 use strict;use warnings;

于 2013-08-15T12:54:44.437 回答