只是不能让perl按预期工作(条件和变量声明)

twh00eeo  于 11个月前  发布在  Perl
关注(0)|答案(6)|浏览(127)

编辑:

我会尝试一个更好的解释这一次,这是从我的脚本的确切代码。

#use warnings;
#use Data::Dumper;
open(my $tmp_file, ">>", "/tmp/some_bad.log") or die "Can not open log file: $!\n";
#if( $id_client != "")
@allowed_locations = ();
#print $tmp_file "Before the if: ". Data::Dumper->Dump([\@allowed_locations, $id_client]) . "";
if( $id_client )
{
#    print $tmp_file "Start the if: ". Data::Dumper->Dump([\@allowed_locations, $id_client]) . "";
#    my $q = "select distinct id_location from locations inner join address using (id_db5_address) inner join zona_rural_detaliat using (id_city) where id_client=$id_client";
#    my $st =  &sql_special_transaction($sql_local_host, $sql_local_database, $sql_local_root, $sql_local_root_password, $q);
#    print $tmp_file "Before the while loop: ref(st)='". ref($st) . "\n";
#    while((my $id)=$st->fetchrow())
#    {
#       print $tmp_file "Row the while loop: ". Data::Dumper->Dump([$id])  . "";
#       my $id = 12121212;
#       push(@allowed_locations, $id);
#    }
#    print $tmp_file "After the while loop: ref(st)='". ref($st) . "\n";
#    my($a) = 1;
#} else {
#    my($a) = 0;    
}
#print $tmp_file "After the if: ". Data::Dumper->Dump([\@allowed_locations, $id_client]) . "";
close($tmp_file) or die "Can not close file: $!\n";
#&html_error(@allowed_locations);

字符串
首先,有人说我应该尝试在命令行中运行它,脚本在命令行中运行良好(没有警告,然后未注解),但当尝试通过Apache在浏览器中加载时失败,请参阅this video,我在那里捕获了脚本行为,我试图在视频中显示:
我打开了两个标签,第一个标签没有定义变量$id_client,第二个标签定义了从GET读取的变量$id_client:?id_client=36124 =>$id_client = 36124;,这两个标签都包含了视频“locallib.pl”中的库
1.当运行带有所有新代码注解的脚本时,
1.当uncoment定义**@allowed_locations =()的行时;脚本失败
1.保留此定义并取消if块的注解,并在if块中取消
my $a;的定义;现在脚本在定义了$id_client时工作正常,但在未定义$id_client时失败
1.取消else块和else块中
my $a;的定义。
1.现在注解所有
my $a;定义并注解else块,脚本失败
1.但是如果我在IF之前使用
open()打开文件,在IF之后使用close()**关闭文件,那么即使IF块为空,也不会失败,如果没有else块,则会发生事件。
我已经复制了在命令行中运行脚本时的所有步骤,并且脚本在每个步骤之后都可以工作。
我知道这听起来像是脚本的行为,但请观看视频(2分钟),也许你会注意到我做错了什么。
使用perl版本:

[root@db]# perl -v
This is perl, v5.8.6 built for i386-linux-thread-mult


有人问我是否没有测试服务器,回答:没有,我的公司有一个生产服务器,有多种用途,不仅是Web界面,我不能冒险更新内核或Perl版本,也不能冒险安装任何调试器,因为公司所有者说:“如果它工作,别管它”,对他们来说,解决方案是**my($a);**是完美的,因为它的工作,我问这里只是为了我,学习更多关于perl,并了解哪里出了问题,我下次可以做得更好。

**编辑:**我成功启动了错误日志记录,并在导致失败的每一步后的错误日志中发现了这一点,我得到了以下消息:

[Thu[error] locallib.pl does not return a true value at /var/www/html/rdsdb4/cgi-bin/clients/quicksearch.cgi line 2.
[Thu Jul 15 14:29:19 2010] [error]脚本头过早结束:quicksearch.cgi
我发现这段代码位于locallib.pl中主代码的末尾,在这之后还有子定义,而locallib.pl是一个库而不是程序文件,所以它的最后一条语句必须返回true。,库末尾的一条简单的**1;**语句确保了这一点(我把它放在子定义之后,以确保noobody在1;之后编写主代码),问题得到了解决。
不知道为什么在CLI它没有问题.

pgccezyw

pgccezyw1#

1.你需要明确地检查definedness。
如果你想在定义了$client之后进入循环,可以使用if ( defined $client )
如果你想在$client被定义并且是一个有效的整数时进入循环,使用if ( defined $client && $client =~ /^-?\d+$/ )。我假设它是一个来自上下文的整数,如果它可以是一个浮点数,正则表达式需要增强-有一个标准的Perl库包含预封装的正则表达式,包括匹配浮点数的正则表达式。如果你需要一个非负的int,从正则表达式的开始删除-?
如果你想在定义了$client并且它是一个非零值(并且假设它不应该是一个空字符串)的时候进入循环,那么使用if ( $client )
如果你想在定义了$client并且是一个有效的非零int的时候进入循环,使用if ( $client && $client =~ /^-?\d+$/ )
1.当if条件为false时,您的@ids为“undef”,如果它依赖于@ids是一个数组,则稍后可能会中断代码。由于您实际上没有指定如何在没有else的情况下中断脚本,因此这是最可能的原因。
请查看此版本是否有效(使用上面您需要的任何“if”条件,我选择了最后一个,因为它似乎与原始代码的意图最接近-仅输入非零整数):

带调试的简化代码

use Data::Dumper;
open(my $tmp_file, ">", "/tmp/some_bad.log") or die "Can not open log file: $!\n";
@ids = (); # Do this first so @ids is always an array, even for non-client!
print $tmp_file "Before the if: ". Data::Dumper->Dump([\@ids, $client]) . "\n";
if ( $client && $client =~ /^-?\d+$/ ) # First expression catches undef and zero
{
    print $tmp_file "Start the if: ". Data::Dumper->Dump([\@ids, $client]) . "\n";
    my $st = &sql_query("select id from table where client=$client");
    print $tmp_file "Before the while loop: ref(st)='". ref($st) . "'\n";
    while(my $row = $st->fetchrow())
    {
       print $tmp_file "Row the while loop: ". Data::Dumper->Dump([row])  . "'\n";
       push(@ids, $row->[0]);
    }
    print $tmp_file "After the while loop: ref(st)='". ref($st) . "'\n";
    # No need to undef since both variables are lexically in this block only
}
print $tmp_file "After the if\n";
close($tmp_file) or die "Can not close file: $!\n";

字符串

oknwwptz

oknwwptz2#

当检查字符串时,==和!=应该分别是'eq'或'ne'

if( $client != "" )

字符串

if( $client ne "" )


否则你不会得到你想要的。

tjjdgumg

tjjdgumg3#

始终开始您的脚本:

use warnings;
use strict;

字符串
这些会给你提供给予有用的信息。
然后你可以写:

my @ids;

if (defined $client) {
    @ids = (); # not necessary if you run this part only once
    my $st = sql_query("select id from table where client=$client");
    while( my ($id) = $st->fetchrow ) {
       push @ids, $id;
    }
} else {
    warn '$client not defined';
}

if (@ids) {  # Your query returned something
    # do stuff with @ids
} else {
    warn "client '$client' does not exist in database";
}

lyfkaqu1

lyfkaqu14#

而不是

if( $client != "" )

字符串
尝试

if ($client)


另外,如果您

use warnings;
 use strict;

nhaq1z21

nhaq1z215#

我发现这段代码位于locallib.pl中主代码的末尾,在这之后还有子定义,而locallib.pl是一个库而不是程序文件,所以它的最后一条语句必须返回true,在库的末尾有一个简单的1;语句可以确保(把它放在子定义之后,以确保noobody在1;之后的主代码中编写代码),问题得到了解决。
结论是:

我学到了每次编写或修改一个库时,确保它的最后一个语句返回true;

pobjuy32

pobjuy326#

哦天...试试这个例子...

# Move the logic into a subroutine
# Forward definition so perl knows func exists
sub getClientIds($);       

# Call subroutine to find id's - defined later.
my @ids_from_database = &getClientIds("Joe Smith");

# If sub returned an empty list () then variable will be false.
# Otherwise, print each ID we found.

if (@ids_from_database) {
    foreach my $i (@ids_from_database) {
        print "Found ID $i \n";
    }
} else {
    print "Found nothing! \n";
}

# This is the end of the "main" code - now we define the logic.

# Here's the real work    
sub getClientIds($) {
    my $client = shift @_;       # assign first parameter to var $client
    my @ids    = ();             # what we will return

    # ensure we weren't called with &getClientIds("") or something...
    if (not $client) {
        print "I really need you to give me a parameter...\n";
        return @ids;
    }

    # I'm assuming the query is string based, so probably need to put it 
    # inside \"quotes\"
    my $st = &sql_query("select id from table where client=\"$client\"");

    # Did sql_query() fail?
    if (not $st) {
        print "Oops someone made a problem in the SQL...\n";
        return @ids;
    }

    my @result;

    # Returns a list, so putting it in a list and then pulling the first element
    # in two steps instead of one.
    while (@result = $st->fetchrow()) {
        push @ids, $result[0];
    }

    # Always a good idea to clean up once you're done.
    $st->finish();

    return @ids;
}

字符串
针对您的具体问题:
1.如果你想测试$client是否被定义,你需要**“if(eval { defined $client; })",但这几乎肯定不是你要找的!确保$client在程序的早期就有一些定义要容易得多(例如$client =“";)。还要注意Kaklon关于ne!=**之间的区别的回答。
1.**if(X){ stuff } else { }不是有效的perl。你可以这样做:if(X){ stuff } else { 1; }但这有点回避问题,因为真实的问题是变量的测试,而不是else子句。
1.抱歉,没有线索-我想问题出在别处。
我也赞同Kinopiko的建议,在程序的开头添加
“use strict;”
。这意味着你使用的任何$variable @that %都必须被预定义为
“my $varable; my @that; my %you;"**这看起来工作量很大,但比在代码中处理未定义变量和已定义变量要少。这是一个很好的习惯。
请注意,my变量只存在于定义它们的squiggliez中(整个文件周围都有隐式的squiggliez:

my $x = 1;
if ($x == 1) 
{
    my $x = 2;
    print "$x \n";    # prints 2. This is NOT the same $x as was set to 1 above.
}
print "$x \n";        # prints 1, because the $x in the squiggliez is gone.

相关问题