我是Perl的新手,我正在尝试将几个.pm文件合并到一个脚本中。大多数模块都可以很好地复制,但是有些模块在到达文件末尾时会出错,但脚本会继续打印。以下是代码示例:
$copy_line = 0;
sysopen(FILE, $file_path, O_WRONLY | O_CREAT, 0711);
sysopen(MODULE, $module_path, O_RDONLY | O_EXCL);
while(<MODULE>)
{
my $line = $_;
if(($line ne "# START\n") and ($copy_line eq 0))
{
}
else
{
print FILE "$line";
$copy_line = 1;
}
}
close FILE;
close MODULE;
每个模块都有开始和结束标记,我不复制任何use语句,所以我知道何时停止复制。该模块的一个例子是
#!/usr/bin/perl
# START
some code to copy over
some more code to copy
even more code to copy
# END
在某些文件中发生的事情是我看到结束标记,然后是模块中重复的代码。输出看起来像
# START
some code to copy over
some more code to copy
even more code to copy
# END
code to copy
even more code to copy
# END
可能导致这种情况的原因是什么? 谢谢,
-rusty
答案 0 :(得分:2)
您的脚本存在各种问题:
你没有显示整个剧本;默认情况下,O_WRONLY
之类的常量不存在。
因此,您可能在脚本开头没有use strict; use warnings;
。这是必要的,以警告错误或可能的错误。
strict
模式要求您声明所有变量。您可以使用my
关键字执行此操作,例如my $copy_line = 0
。
永远不要使用sysopen
,除非您完全理解open
的工作原理以及为什么它不是特定情况下的最佳选择。考虑到我没有那种知识水平,我认为我们会坚持正常open
。
open
采用变量,模式和文件名,如
open my $file, "<", $filename;
我建议你use autodie
进行自动错误处理,否则你应该
open my $file, "<", $filename or die "Can't open $filename: $!";
其中$!
包含错误原因。您可以指定open的各种模式,这些模式是在shell重定向运算符之后建模的。重要的是:<
读取,>
写入(或创建),>>
追加,|-
将管道写入命令,-|
从命令读取管道。
eq
运算符测试字符串相等性。如果要测试数字相等性,请使用==
运算符。
if (COND) {} else { STUFF }
宁可写成unless (COND) {STUFF}
。
您已成功实施了一些开始在START
标记处复制的扭曲逻辑。但是,您不会停留在END
。对于这样的东西,可以使用触发器 - 运算符 ..
:它需要两个操作数,它们是任意表达式。运算符返回false直到第一个操作数为true,并且在第二个操作数返回true之后保持为true。如果一个操作数是常量整数,则将其解释为行号。因此,脚本
while (<>) {
print if 5 .. 10;
}
打印包含输入的第5-10行。
对于您的问题,您应该使用与开始和结束标记匹配的正则表达式:
while (<>) {
print if /^ \s* # \s* START/x .. /^ \s* # \s* END/x
}
我在这里假设您知道正则表达式,但如果需要,我可以添加解释。
如果在没有操作数的情况下使用readline操作符<>
,它将获取脚本的命令行参数,打开它们并按顺序读取它们。如果没有提供参数,则使用STDIN。
这允许灵活的小脚本。代码可以在命令行oneliner
中汇总$ perl -ne'print if /^\s*#\s*START/../^\s*#\s*END/' INPUT-FILE1 INPUT-FILE2 >OUTPUT
这有两个问题:
# END
,则下一个文件将全部打印出来,直到找到下一个# END
。我们可以通过在终止条件下测试文件结尾来缓解问题#2:
print if /^\s*#\s*START/ .. (/^\s*#\s*END/ or eof);
问题#1稍微复杂一些;我会为此重新引入一面旗帜:
my $print_this = 0;
while (<>) {
if (/^\s*#\s*END/ or eof) {
$print_this = 0;
} elsif ($print_this) {
print;
} elsif (/^\s*#\s*START/) {
$print_this = 1;
}
}
部分测试用例:
$ perl -e'
my $print_this = 0;
while (<>) {
if (/^\s*#\s*END/ or eof) { $print_this = 0 }
elsif ($print_this) { print }
elsif (/^\s*#\s*START/) { $print_this = 1 }
}' <<'__END__'
no a 1
no a 2
# START
yes b 1
yes b 2
yes b 3
#END
no c 1
no c 2
# START
yes d 1
# END
no e 1
__END__
输出:
yes b 1
yes b 2
yes b 3
yes d 1
答案 1 :(得分:0)
如果您在不修改内容的情况下复制文件,则应该查看File::Copy
http://perldoc.perl.org/File/Copy.html
File::Copy
是一个标准模块,与Perl一起安装。有关标准模块的列表,请参阅perldoc perlmodlib
http://perldoc.perl.org/perlmodlib.html#Standard-Modules