系统调用中的Perl正则表达式

时间:2011-04-05 19:02:38

标签: regex perl command-line

以下Perl单行程按预期工作;它剥离我的前导和尾随退格的文件,并用一个标签替换中间空格:

$ perl -pi -le 's/^\s+//; s/\s+$//; s#\s+#\t#g;' file

令我困惑的是为什么我无法通过我的Perl代码中的system调用来实现此目的:

system "perl -pi -le 's/^\s+//; s/\s+\$//; s#\s+#\t#g;' file";  # '$' backslashed

这里有什么问题?

8 个答案:

答案 0 :(得分:3)

没有必要为-i启动另一个进程,但通常你应该本地化一些全局变量:

sub do_stuff {
  my $file = shift;
  local ($_, $., $ARGV, *ARGV);
  local ( $^I, @ARGV ) = ( '.bak', $file );

  while ( <> ) {
    s/..../..../;
    print;
  }
}

答案 1 :(得分:2)

say "perl -pi -le 's/^\s+//; s/\s+\$//; s#\s+#\t#g;' file";

产生

Unrecognized escape \s passed through at -e line 1.
Unrecognized escape \s passed through at -e line 1.
Unrecognized escape \s passed through at -e line 1.
perl -pi -le 's/^s+//; s/s+$//; s#s+#   #g;' file

你想要

system("perl -pi -le 's/^\\s+//; s/\\s+\$//; s#\\s+#\\t#g;' file");

实际上,为什么要调用shell?

system('perl', '-i', '-ple' 's/^\\s+//; s/\\s+$//; s#\\s+#\\t#g;', 'file');

答案 2 :(得分:1)

您忘记首先将反斜杠解析为Perl双引号字符串,然后再作为shell命令解析。

等同于命令行:

perl -pi -le 's/^\s+//; s/\s+$//; s#\s+#\t#g;' file

在Perl脚本中

system "perl -pi -le 's/^\\s+//; s/\\s+\$//; s#\\s+#\\t#g;' file"

虽然为此启动另一个Perl副本是愚蠢的。你可能最好再使用几行代码并在同一个过程中完成它。

答案 3 :(得分:1)

runrig展示了如何使用-i不必创建子进程。在内部使用-i有点奇怪,所以有两个更清晰的选择。第一种是使用Tie::File,这非常简单。

另一种是使用File::Temp写入临时文件,这基本上就是-i所做的。

my $tmp = File::Temp->new;
open my $fh, "<", $file or die "Can't open $file: $!";

while(<$fh>) {
    s/.../.../;
    print $tmp $_;
}

my $tmpfile = $tmp->filename;
rename $tmpfile, $file or die "Can't rename $tmpfile to $file: $!";

答案 4 :(得分:0)

内部双引号'具有功能值。您的字符串将由Perl编辑。我的测试显示您丢失了\s个表达式。它还插入了'\t'。选项卡 - 虽然这可能不是问题所在。

以下是Data::Dumper

$s = 'perl -pi -le \'s/^s+//; s/s+$//; s#s+#    #g;\' file';

答案 5 :(得分:0)

双引号正在解释一切。

尝试:

system "perl -pi -le 's/^\\s+//; s/\\s+\$//; s\#\\s+\#\\t\#g;' file";

答案 6 :(得分:0)

for Linux try

system q(perl -pi -le 's/^\s+//; s/\s+$//; s#\s+#\t#g;' file); # comments here

for M $ windows:

system q(perl -pi -le "s/^\s+//; s/\s+$//; s#\s+#\t#g;" file); # comments here

答案 7 :(得分:0)

这就是Larry为我们提供备用引号字符的情况。我们想对system()s arg使用单引号,这样我们就不必弄清楚需要反斜杠的内容,但我们在引用的字符串本身中也需要单引号。所以,替代引用字符来救援!

system q(perl -p -le 's/^\s+//; s/\s+$//; s#\s+#\t#g;' file);

现在,您可以将在命令行中工作的内容直接复制/粘贴到Perl源中。