程序删除我文件中的行

时间:2013-05-21 13:58:34

标签: perl lines

我有一个程序,我试图用管道(|)锚定行的开头。但是,当我执行它时,它会减少或删除我文件中的行。正如您将看到的,我并不是想要替换任何东西,只需要放置在某些行的开头。这是程序:

$DESCRIPTION = qr/^[0-9]+\.[0-9]+ +.*? {2,}[0-9]+.*? {2,}[0-9]+.*? {2,}[0-9]+.*? {2,}[0-9]+.*?$/;
$PRICELINE = qr/^[0-9]+.*? {2,}[0-9]+.*?$/;
$PRICELINE2 = qr/^.*? {2,}[0-9]+\.[0-9]+ {2,}[0-9]+\$/;
$CODE = qr/^\w{9}$/;
$date = qr/^AS OF.*?$/;
$accountnumber = qr/^ACCOUNT NUMBER.*?$/;
$name = qr/^CEOTID.*?$/;

while (<>) {
    if (s/($DESCRIPTION)/\|$1/gi) {print STDOUT "1\n"; next LINE;};
    if (s/($PRICELINE)/\|$1/gi) {print STDOUT "2\n"; next LINE;};
    if (s/($PRICELINE2)/\|$1/gi) {print STDOUT "3\n"; next LINE;};
    if (s/($CUSIP)/\|$1/gi) {print STDOUT "4\n"; next LINE;};
    if (s/($date)/\|$1/g) {print STDOUT "5\n"; next LINE;};
    if (s/($accountnumber)/\|$1/gi) {print STDOUT "6\n"; next LINE;};
    if (s/($name)/\|$1/gi) {print STDOUT "7\n"; next LINE;};
    print;  
}
print "\n\ndone"

我试图一次消除一个变量,看看哪一个导致了故障,但仍然没有运气。我也只是使用了while语句,但它很慢并且仍然删除了我文件的第一行。

任何帮助都会很棒。

2 个答案:

答案 0 :(得分:4)

编辑:请注意,您有一个未声明的变量$CUSIP,您似乎与$CODE混淆了。如果未启用strictwarnings,则此错误将是静默且致命的,但几乎不谨慎,因为它会在您的输入中插入管道符号。

我会猜测并说这是因为您尝试使用未定义的标签:LINE。此标签以下列方式使用:

LINE: while (<>) {

    ... next LINE;
}

但你可以轻松地跳过它,然后只说next,它将引用最里面的循环。但是,当你没有标签时,我的测试中似乎发生的事情就是它会以错误退出循环

Label not found for "next LINE" at ...

即使warnings关闭,也会显示此错误。它永远不应该是。您编写的任何脚本的前两行应为:

use strict;
use warnings;

因为它会让你的生活更轻松。

你也应该知道你可以使用先行断言来解决你想要做的事情:

if (s/(?=$DESCRIPTION)/|/i) { ... }

你应该意识到这一点:

print STDOUT "1\n";
如果您通过-p-i开关使用就地编辑,

..仍然会打印到文件中。如果您需要某种反馈,可以打印到STDERR:

print STDERR "1\n";
warn "1\n";          # same thing

此外,您根本不必使用s///运算符,只需检查该行,然后使用字符串插值添加管道符号:

if (/$DESCRIPTION/) { $_ = "|$_" }

此外,您根本不必使用next:您可以使用普通的旧式逻辑:

if (/$DESCRIPTION/) { ... }
elsif (/$PRICELINE/) { ... }

所以你有它。请开始使用strictwarnings

答案 1 :(得分:1)

LINE: while (<>) {
    if (s/($DESCRIPTION)/\|$1/gi) {print STDOUT "1\n"; next LINE;};
    ...
    print;  
}

当执行next LINE语句时,执行会返回到循环的顶部。你的最终print语句永远不会被执行,似乎某些行被“删除”。

Perl提供while(EXPR) { BLOCK } continue { BLOCK }语法,以便您可以在迭代结束时执行一些任意代码。您可以将print语句放在continue块中:

LINE: while (<>) {
    if (s/($DESCRIPTION)/\|$1/gi) {print STDOUT "1\n"; next LINE;};
    if (s/($PRICELINE)/\|$1/gi) {print STDOUT "2\n"; next LINE;};
    if (s/($PRICELINE2)/\|$1/gi) {print STDOUT "3\n"; next LINE;};
    if (s/($CUSIP)/\|$1/gi) {print STDOUT "4\n"; next LINE;};
    if (s/($date)/\|$1/g) {print STDOUT "5\n"; next LINE;};
    if (s/($accountnumber)/\|$1/gi) {print STDOUT "6\n"; next LINE;};
    if (s/($name)/\|$1/gi) {print STDOUT "7\n"; next LINE;};
} continue {
    print;  
}

现在,即使执行了print个子句之一,您的if语句也会被执行。