sed命令在命令行上工作但不在perl脚本中

时间:2017-10-13 05:46:21

标签: linux perl sed

我有一个文件,其中我必须替换所有单词,如$ xyz,对于他们我必须替换像这样:

$xyz with ${xyz}.
$abc_xbs with ${abc_xbc}
$ab,$cd  with ${ab},${cd}

这个文件也有一些像$ {abcd}这样的词,我不需要改变。 我正在使用此命令

sed -i' s?\ $([A-Z _] +)?\ $ {\ 1}?g'文件

它在命令行上工作正常但不在perl脚本中

sed -i 's?\$\([A-Z_]\+\)?\$\{\1\}?g' file;

我缺少什么? 我认为添加一些反斜杠会有所帮助。我尝试添加一些但没有成功。

由于

1 个答案:

答案 0 :(得分:1)

在Perl脚本中,您需要有效的Perl语言,就像在C程序中需要有效的C文本一样。在终端sed..中,shell被理解并作为命令运行,但在Perl程序中,它只是一堆单词,而sed..行不是Perl。

你需要在qx()(反引号)或system()中使用它,以便它作为外部命令运行。那么你确实需要" 一些反斜杠,"这是事情变得有点挑剔的地方。

但为什么要从Perl脚本运行sed命令?使用Perl完成工作

use warnings;
use strict;
use File::Copy 'move';

my $file     = 'filename';
my $out_file = 'new_' . $file;

open my $fh,     '<', $file     or die "Can't open $file: $!";
open my $fh_out, '>', $out_file or die "Can't open $out_file: $!"; 

while (<$fh>) 
{
    s/\$( [^{] [a-z_]* )/\${$1}/gix;
    print $fh_out $_;
}
close $fh_out;
close $fh;

move $out_file, $file or die "Can't move $out_file to $file: $!";

正则表达式使用否定字符类 [^...]来匹配{之后的$以外的任何字符,从而排除已经支撑的字词。然后它匹配一系列字母或下划线,如问题中所示(可能没有,因为第一个非{已经提供了至少一个)。

使用5.14+,您可以使用非破坏性 /r modifier

print $fh_out s/\$([^{][a-z_]*)/\${$1}/gir;

返回更改的字符串(原始文件未更改),右侧为print

输出文件最后移到原始文件上,应该使用File::Temp。以这种方式覆盖原始版本会更改$file的inode编号;如果这是一个问题,请参阅this post,例如,如何更新原始inode。

单行(命令行)版本,可以轻松测试

perl -wpe's/\$([^{][a-z_]*)/\${$1}/gi' file

这仅打印到控制台。要更改原始内容,请添加-i(就地)或-i.bak以保留备份。

一个合理的问题&#34; 不是更短的方式&#34;来了

这是一个,使用方便Path::Tiny的文件不是很大,所以我们可以把它读成一个字符串。

use warnings;
use strict; 
use Path::Tiny;

my $file     = 'filename';
my $out_file = 'new_' . $file;

my $new_content = path($file)->slurp =~ s/\$([^{][a-z_]*)/\${$1}/gir;

path($file)->spew( $new_content );

第一行将文件读入一个字符串,替换运行在该字符串上;返回已更改的文本并将其分配给变量。然后,带有新文本的变量将写在原始文件上。

通过将第一个表达式替换为第二个变量,可以将两条线压缩为一条线。但是在一个(复杂)语句中两次打开相同的文件并不是完全可靠的做法,我不会推荐这样的代码。

但是,由于模块的版本为0.077,你可以很好地做到

path($file)->edit_lines( sub { s/\$([^{][a-z_]*)/\${$1}/gi } );

或使用edit将文件粘贴到字符串中并将回调应用于该字符串。

所以这毕竟是一条很好的路线。

我想补充说,削减代码行代码并不值得付出努力,但如果它干扰了对代码结构和正确性的关注,肯定会导致麻烦。但是,Path::Tiny是一个很好的模块,这是合法的,虽然它确实缩短了很多东西。