组织大量替换的一种方法
use warnings;
use strict;
use feature 'say';
my %repl = (
really_long_function_name1 => 'A00128',
really_long_function_name2 => 'A00060',
# ...
);
my $re = join '|', keys %repl; # add quotemeta if needed. see text
while (<>) {
s/\b($re)\b/$repl{$1}/g;
print
}
The <> operator https://perldoc.perl.org/perlop#I/O-Operators reads line by line files with names given on the command line. Each line, changed or not, is merely printed so this acts as a filter. If the files need be edited in place then the code need be adjusted for that.†
如果模式中使用的任何键可以具有正则表达式专用的符号,则应该对它们进行转义,并且有一个工具是引用元 https://perldoc.perl.org/functions/quotemeta --
join '|', map { quotemeta } keys %repl
。但这里的键是 C 程序中的函数名称。
这并不能解决某些问题(如果某些替换包含在其他替换中怎么办?),并且可能需要根据细节进行其他调整。我不太明白所有要点,特别是为什么将替换列表打印到文件中。如果这很重要,则可以从具有方便格式的文件中读取上面的替换对(Perl 数据结构的转储?JSON
? Or YAML
这样它也很好读?)
通过向散列添加替换对,可以轻松编辑/扩展该列表。
† One way is shown in the SO page linked in the question: set the $^I global variable https://perldoc.perl.org/perlvar#%24%5EI (value of the -i
switch). With it being an empty string input files are changed "in-place" but we don't get a backup, otherwise its value is added as a suffix to the backup files
local $^I = ''; # changes made to input files. no backup
while (<>) {
s/\b($re)\b/$repl{$1}/g;
print;
}
or
local $^I = '.bak'; # added suffix for the backup file(s)
while (<>) {
s/.../.../g;
print;
}
确保此代码的范围足够小,以便能够使用local https://perldoc.perl.org/functions/local限制这种变化——这样解释器的其余部分就不会受到影响!
或者,如果感觉不好,请手动处理文件列表。一旦程序被调用
progname [options] file1 file2...
然后在运行的程序中数组@ARGV https://perldoc.perl.org/perlvar#@ARGV包含命令行中的所有单词(程序名称除外)。
As @ARGV
被处理Getopt::Long
破折号选项(带有-
or --
)被删除,剩下的@ARGV
are file1
, file2
(等)文件名。所以之后Getopt::Long
您可以执行的已处理选项
foreach my $filename (@ARGV) {
# handle the file $filename
}
或者,从以下位置复制文件名@ARGV
从那里到他们自己的数组和进程的安全。 (或者,可以将文件名作为选项的一部分,这样它们将被提取Getopt::Long
.)
如果您处理这样的文件(而不是让“钻石”运算符<>
这样做)然后还有一些库可以就地更改文件,例如路径::微小::edit_lines https://metacpan.org/pod/Path::Tiny#edit_lines,-edit_lines_utf8,-edit_lines_raw
use Path::Tiny;
path($filename)->edit_lines( sub { s/\b($re)\b/$repl{$1}/g } );