0

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

$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 语句,但它很慢并且仍然删除了我文件的第一行。

任何帮助都会很棒。

4

2 回答 2

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";

..如果您通过-pand-i开关使用就地编辑,仍然会打印到文件中。如果您需要某种反馈,可以打印到 STDERR:

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

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

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

此外,您根本不必使用next:您可以使用简单的老式逻辑:

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

所以你有它。请开始使用strictand warnings

于 2013-05-21T14:21:18.080 回答
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子句,您的语句也总是会执行。

于 2013-05-21T14:47:44.137 回答