只是无法让 Perl 按预期工作(条件和变量声明)
编辑:
这次我会尝试更好的解释,这是我的脚本中的确切代码。
#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 失败,请观看此视频,我在其中捕获了脚本行为,我试图在视频中展示:
我打开了 2 个选项卡,第一个选项卡没有定义变量 $id_client,第二个选项卡定义了从 GET 读取的变量 $id_client: ?id_client=36124 => $id_client = 36124; ,两者都包含视频中的库“locallib.pl”,
- 当使用所有 新代码注释了页面加载
- 当取消注释定义的行时, @allowed_locations = (); 该 脚本失败请
- 保留此定义并取消注释 if 块,以及定义 my $a; 在 if 块中;现在,当 $id_client 为时,脚本可以正常工作 已定义,但在 $id_client 时失败 未定义
- 取消注释 else 块和 else 中 my $a; 的定义 堵塞。现在脚本运行良好 无论有没有 $id_client,
- 现在评论所有 my $a; 定义并评论其他 块,脚本失败
- ,但如果我使用 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 Jul 15 14:29:19 2010] [错误] locallib.pl 未在 /var/www/html/rdsdb4/cgi-bin/clients/quicksearch.cgi 第 2 行返回真值。
[Thu Jul 15 14:29:19 2010] [error] 脚本头过早结束:quicksearch.cgi
我发现这段代码位于 locallib.pl 中主代码的末尾,之后有子定义,并且 locallib.pl 是一个库而不是程序文件,因此 它的最后一条语句必须返回 true。 ,库末尾的简单 1; 语句确保(我将其放在子定义之后,以确保没有人在 1;) 之后的主程序中编写代码,问题得到解决。
不知道为什么在 CLI 中没有问题......
EDIT:
I will try a better explication this time, this is the exact code from my script.
#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);
First off all, somebody said that I should try to run it in command line, the script works fine in command line (no warnings, It was uncommented then), but when triyng to load in via apache in the browser it fails, please see this video where I captured the script behavior, what I tried to show in the video:
I have opened 2 tabs the first doesn't define the variable $id_client, the second defines the variable $id_client that is read from GET: ?id_client=36124 => $id_client = 36124; , both of them include the library in the video "locallib.pl"
- When running the script with all the
new code commented the page loads - when uncoment the line that defines
the @allowed_locations = (); the
script fails - leave this definition and uncoment
the if block, and the definition of
my $a; in the if block; Now the script works fine when $id_client is
defined, but fails when $id_client
is not defined - Uncoment the else block and the
definition of my $a; in the else
block. Now the script works fine
with or without $id_client - now comment all the my $a;
definisions and comment the else
block, the script fails - but if I'm using open() to open
a file before the IF, and
close() to close it after the if it does't fail even if the IF block
is empty and event if there is no
else block
I have replicated all the steps when running the script in the command line, and the script worked after each step.
I know it sounds like something that cannot be the behavior of the script, but please watch the video (2 minutes), maybe you will notice something that I'm doing wrong there.
Using perl version:
[root@db]# perl -v
This is perl, v5.8.6 built for i386-linux-thread-mult
Somebody asked if I don't have a test server, answer: NO, my company has a production server that has multiple purposes, not only the web interface, and I cannot risk to update the kernel or the perl version, and cannot risk instaling any debuger, as the company owners say: "If it works, leave it alone", and for them the solution with my ($a); is perfect beacause it works, I'm asking here just for me, to learn more about perl, and to understand what is going wrong and what can I do better next time.
EDIT:
I had success starting the error logging, and found this in the error log after each step that resulted in a failure I got this messages:
[Thu Jul 15 14:29:19 2010] [error] locallib.pl did 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] Premature end of script headers: quicksearch.cgi
What I found is that this code is at the end of the main code in the locallib.pl after this there are sub definitions, and locallib.pl is a library not a program file, so it's last statement must returns true. , a simple 1; statement at the end of the library ensures that (I put it after sub definitions to ensure that noobody writes code in the main after the 1;) and the problem was fixed.
Don't know why in CLI it had no problem ...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您需要明确检查定义。
如果要在定义$client时进入循环,
使用
if(已定义$client)
。如果你想在$client被定义并且是一个有效的整数时进入循环,
使用
if (已定义 $client && $client =~ /^-?\d+$/ )
。我假设它是上下文中的整数,如果它可以是浮点数,则需要增强正则表达式 - 有一个标准 Perl 库,其中包含预装正则表达式,包括匹配浮点数的正则表达式。如果您需要非负整数,请从正则表达式的开头删除
-?
。如果您想在定义 $client 且非零时进入循环(并假设它不应该是空字符串),
使用
if ( $client )
。如果要在定义 $client 且为有效的非零整数时进入循环,
使用
if ( $client && $client =~ /^-?\d+$/ )
。当
if
条件为 false 时,您的 @ids 为“undef”,如果代码依赖于 @ids 为数组,则稍后可能会破坏代码。由于您实际上并未指定脚本在没有else
的情况下如何中断,因此这是最可能的原因。请查看此版本是否有效(使用上面您需要的任何“if”条件,我选择了最后一个,因为它似乎与原始代码的意图最接近 - 仅输入非零整数):
更新代码带调试
You need to explicitly check for definedness.
If you want to enter the loop when $client is defined,
use
if ( defined $client )
.If you want to enter the loop when $client is defined and a valid integer,
use
if ( defined $client && $client =~ /^-?\d+$/ )
.I assume it's an integer from the context, if it can be a float, the regex needs to be enhanced - there's a standard Perl library containing pre-canned regexes, including ones to match floats. If you require a non-negative int, drop
-?
from regex's start.If you want to enter the loop when $client is defined and a non-zero (and assuming it shouldn't ever be an empty string),
use
if ( $client )
.If you want to enter the loop when $client is defined and a valid non-zero int,
use
if ( $client && $client =~ /^-?\d+$/ )
.Your @ids is "undef" when
if
condition is false, which may break the code later on if it relies on @ids being an array. Since you didn't actually specify how the script breaks without anelse
, this is the most likely cause.Please see if this version works (use whichever "if" condition from above you need, I picked the last one as it appears to match the closest witrh the original code's intent - only enter for non-zero integers):
UPDATED CODE WITH DEBUGGING
当检查字符串时, == 和 != 应该分别是 'eq' 或 'ne'
应该是
否则你不会得到你期望得到的东西。
when checking against a string, == and != should be respectively 'eq' or 'ne'
should be
Otherwise you don't get what you're expecting to get.
始终以 开头:
这些将为您提供有用的信息。
然后你可以写:
Always begin your script with :
these will give you usefull informations.
Then you could write :
而不是
尝试
如果你这样做,Perl 调试会更容易,
Instead of
try
Also, Perl debugging is easier if you
我发现这段代码位于locallib.pl中主代码的末尾,之后有子定义,而locallib.pl是一个库而不是程序文件,所以它的最后一条语句必须返回true< /strong>,简单的 1;库末尾的语句确保(将其放在子定义之后,以确保没有人在 1 之后的主程序中编写代码;)并且问题得到解决。
结论:
我了解到,每次编写或修改库时,请确保最后一条语句返回 true;
What I found is that this code is at the end of the main code in the locallib.pl after this there are sub definitions, and locallib.pl is a library not a program file, so it's last statement must returns true, a simple 1; statement at the end of the library ensures that (put it after sub definitions to ensure that noobody writes code in the main after the 1;) and the problem was fixed.
The conclusion:
I have learned that every time you write a library or modify one, ensure that it's last statment returns true;
哦天哪...试试这个作为例子...
对于您的具体问题:
我也赞同 Kinopiko 的建议,建议您在程序开头添加“use strict;”。这意味着任何 $variable @that %you 使用都必须预先定义为 "my $varable; my @that; my %you;" 这可能看起来需要更多工作,但实际上却更少而不是尝试处理代码中未定义的变量与已定义的变量。这是一个值得养成的好习惯。
请注意,my变量仅存在于定义它们的squiggliez中(整个文件周围有隐式的squiggliez:
Oh my... Try this as an example instead...
To your specific questions:
I also echo Kinopiko in recommending you add "use strict;" at the start of your program. That means that any $variable @that %you use has to be pre-defined as "my $varable; my @that; my %you;" It may seem like more work, but it's less work than trying to deal with undefined versus defined variables in code. It's a good habit to get into.
Note that my variables only live within the squiggliez in which they are defined (there's implicit squiggliez around the whole file: