我正在尝试接收一个文件INPUT,如果该文件中的一行包含一个字符串,则将该行替换为其他内容(整行,包括换行符),或者根本不替换任何内容(删除它之类的行)不在那里)。将所有这些写入新文件。
以下是该部分代码......
while(<INPUT>){
if ($_ =~ / <openTag>/){
chomp;
print OUTPUT "Some_Replacement_String";
} elsif ($_ =~ / <\/closeTag>/) {
chomp;
print OUTPUT ""; #remove the line
} else {
chomp;
print OUTPUT "$_\r\n"; #print the original line
}
}
while(<INPUT>)
应该一次读一行(如果我的理解是正确的)并将每一行存储在特殊变量$_
然而,当我运行上面的代码时,我只得到第一个if语句条件返回Some_Replacement_String
,并且只返回一次。 (1行,一个1.3米的文件,预计有600,000个替换)。这显然不是我期望的行为。如果我执行while(<INPUT>){print OUTPUT $_;)
之类的操作,我会获得整个文件的副本,每行,所以我知道正在读取整个文件(预期的行为)。
我要做的是获得一条线,测试它,用它做一些事情,然后继续下一个。
如果它对故障排除有帮助,如果我在while语句(或之后)的任何地方使用print $.;
,我会返回1。我希望这是“访问的最后一个文件句柄的当前行号”。所以当我的while语句遍历整个文件时,它应该等于文件中的行数,而不是1。
我已尝试过此代码的其他一些变体,但我认为这是我最接近的。我假设有一个很好的理由我没有得到我期望的行为,有人能告诉我它是什么吗?
答案 0 :(得分:4)
您描述的问题表明您的输入文件只包含一行。这可能是因为许多不同的事情,例如:
$/
-0777
开关关于您的代码的一些注意事项:
if ($_ =~ / <openTag>/){
chomp;
print OUTPUT "Some_Replacement_String";
无需选择您未使用的线路。
} elsif ($_ =~ / <\/closeTag>/) {
chomp;
print OUTPUT "";
这是多余的。你不需要打印一个空字符串(永远,真的),并选择你没有使用的值。
} else {
chomp;
print OUTPUT "$_\r\n"; #print the original line
无需删除新行,然后将其删除。此外,通常您会使用\n
作为行结尾,即使在Windows上也是如此。
而且,既然你在每个if-else子句中咀嚼,你也可以将它移到整个if块之外。
chomp;
if (....) {
但是既然你不依赖于不在那里的行结尾,为什么还要费心使用chomp
呢?
使用$_
变量时,您可以缩写某些命令,例如您使用chomp
。例如,单独的正则表达式将应用于$_
:
} elsif (/ <\/closeTag>/) { # works splendidly
如上所述,当你有一个包含斜杠的正则表达式时,你可以为正则表达式选择另一个分隔符,这样你就不需要转义斜杠:
} elsif (m# </closeTag>#) {
但是,您需要使用m//
运算符的完整表示法,前面有m
。
所以,简而言之
while(<INPUT>){
if (/ <openTag>/){
print OUTPUT "Some_Replacement_String";
} elsif (m# </closeTag>#) {
# do nothing
} else {
print OUTPUT $_; # print the original line
}
}
当然,最后两个可以组合成一个,带有一些否定逻辑:
} elsif (not m# </closeTag>#) {
print OUTPUT $_;
}