Perl 在脚本内就地编辑(而不是一行)

问题描述 投票:0回答:2

所以,我习惯了

perl -i
使用 perl,就像我会
sed
和就地编辑一样。

$^I
中的
perlvar
的文档:

$^我 就地编辑扩展的当前值。使用 undef 禁用就地编辑。

好的。所以这意味着我也许可以在脚本中进行“就地”编辑?

我遇到的麻烦是:

如果我跑步:

perl -pi -e 's/^/fish/' test_file

然后解析它:

BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/^/fish/;
}
continue {
    die "-p destination: $!\n" unless print $_;
}

现在 - 如果我想在脚本中使用

$^I
,请说:

 foreach my $file  ( glob "*.csv" ) {
     #inplace edit these files - maybe using Text::CSV to manipulate? 
 }

我如何“启用”这种情况发生?这是一个改变

$_
(就像
s/something/somethingelse/
默认情况下那样)并让 perl 隐式打印它的问题吗?还是还有其他事情发生?

我的主要问题是 - 我可以进行应用 CSV 转换(或 XML 调整或类似)的“就地编辑”吗?

我很高兴我可以打开单独的文件句柄、读取/打印等。我想知道是否还有其他方法。 (即使它只是在某些情况下有用)。

perl
2个回答
14
投票

通过

-i
命令行选项或通过设置
$^I
启用的就地编辑行为仅适用于
ARGV
文件句柄。这意味着文件必须在命令行上命名,或者
@ARGV
必须在程序中设置

此程序会将所有 CSV 文件中的所有小写字母更改为大写字母。请注意,我已将

$^I
设置为非空字符串,建议您在测试时这样做,以便保留原始数据文件

use strict;
use warnings;

our $^I = '.bak';

while ( my $file = glob '*.csv' ) {

  print "Processing $file\n";

  our @ARGV = ($file);

  while ( <ARGV> ) {
     tr/a-z/A-Z/;
     print;
  }
}

3
投票

有一个更简单的答案,如果您的脚本总是将进行就地编辑并且您的操作系统使用“shebang”(运行以“#!”开头的脚本):

#!perl -i while (<>) { print "LINE: $_" }
将在给定的每个文件的行开头添加“LINE:”。 (请注意,您可能会使用 perl 的完整路径,即“#!/usr/bin/perl -i”)

您也可以将您的脚本称为:

% perl -i <script> <file1> <file2> ...
如果您没有 shebang 支持,则可以在 file1、file2 等上将脚本作为就地编辑器运行。

© www.soinside.com 2019 - 2024. All rights reserved.