【问题标题】:Perl referencing and deferencing hash values when passing to subroutine?传递给子例程时Perl引用和延迟哈希值?
【发布时间】:2011-10-22 16:09:25
【问题描述】:

我已经为这个问题纠结了大约 5 个小时,我真的很沮丧,需要一些帮助。

我正在编写一个 Perl 脚本,它从 MySQL 表中提取作业,然后执行各种数据库管理任务。当前任务是“创建数据库”。该脚本成功创建了数据库,但是当我为 PHP 开发人员生成配置文件时,它崩溃了。

我认为这是引用和取消引用变量的问题,但我不太确定到底发生了什么。我认为在这个函数调用之后,发生了一些事情 $$result{'databaseName'}。这就是我得到结果的方式:$result = $select->fetchrow_hashref()

这是我的函数调用和函数实现:

函数调用(第 127 行):

generateConfig($$result{'databaseName'}, $newPassword, "php");

功能实现:

sub generateConfig {
    my($inName) = $_[0];
    my($inPass) = $_[1];
    my($inExt)  = $_[2];

    my($goodData) = 1;
    my($select)   = $dbh->prepare("SELECT id FROM $databasesTableName WHERE name = '$inName'");
    my($path)     = $documentRoot.$inName."_config.".$inExt;
    $select->execute();

    if ($select->rows < 1 ) {
            $goodData = 0;
    }

    while ( $result = $select->fetchrow_hashref() )
    {
            my($insert) = $dbh->do("INSERT INTO $configTableName(databaseId, username, password, path)".
                                   "VALUES('$$result{'id'}', '$inName', '$inPass', '$path')");

    }

    return 1;
    }

错误:

Use of uninitialized value in concatenation (.) or string at ./dbcreator.pl line 142.
Use of uninitialized value in concatenation (.) or string at ./dbcreator.pl line 154.

第 142 行:

        $update = $dbh->do("UPDATE ${tablename}
                        SET ${jobStatus}='${newStatus}' 
                        WHERE id = '$$result{'id'}'");

第 154 行:

 print "Successfully created $$result{'databaseName'}\n";

我认为问题出在函数调用的原因是因为如果我注释掉函数调用,一切都会很好!

如果有人能帮助我了解发生了什么,那就太好了。

谢谢,

附言如果您发现将整个密码作为纯文本存储在数据库中存在安全问题,那么在正常工作后将得到解决。 =P

迪伦

【问题讨论】:

    标签: perl hash reference subroutine dereference


    【解决方案1】:

    当我从 Oracle 结果集运行 hetchrow_hashref 时,这让我发疯了。 原来的列名总是以大写形式返回。 因此,一旦我开始以大写形式引用列,问题就消失了: 插入->执行($result->{ID}, $inName, $inPass, $path);

    【讨论】:

      【解决方案2】:

      编辑:阅读您的评论后

      我认为这两个错误都与您使用$$result 有关。如果$resultfetchrow_hashref的返回值,如:

      $result = $select->fetchrow_hashref()
      

      那么引用其值的正确方法应该是:

       print "Successfully created " . $result{'databaseName'} . "\n";
      

      和:

          $update = $dbh->do("UPDATE ${tablename}
                          SET ${jobStatus}='${newStatus}' 
                          WHERE id = '$result{'id'}'");
      

      旧答案:

      在函数generateConfig 中,您可以使用以下语法传递引用:

      generateConfig(\$result{'databaseName'},$newPassword, "php");
      

      $$ 用于取消对字符串的引用;\ 为您提供对其应用对象的引用)。

      然后,在打印语句本身中,我会尝试:

       print "Successfully created $result->{'databaseName'}->{columnName}\n";
      

      确实,fetchrow_hashref 返回一个哈希值(不是字符串)。

      这应该可以解决一个问题。

      此外,您正在使用名为$dbh 的变量,但您没有显示它的设置位置。它是一个全局变量,以便您可以在generateConfig 中使用它吗?执行generateConfig时是否已初始化?

      【讨论】:

      • sergio,感谢您的快速回复。当我在传递 $result{'databaseName'} 时尝试使用 '\' 代替 '$' 时,出现以下错误(我也尝试过):全局符号“%result”需要在 ./ dbcreator.pl 第 127 行。另外,$dbh 是一个全局变量。但是在你提到它之后,我将它作为第四个参数传递给 generateConfig。似乎没有改变什么。迪伦
      • 抱歉,我是 Stack Overflow 的新手。试图弄清楚界面......有没有办法回应更多的空间来正确格式化文本等?
      • sergio,我认为你在第一部分想太多了。如果他想将外部 $result 的某些部分传递给函数,他应该像你在内部函数中那样做同样的事情,$result-&gt;{'databaseName'}
      • @sergio $dbh 是与 CPAN 模块 DBI.pm 关联的常用变量名。 my $dbh = DBI-&gt;connect(......); 返回一个数据库句柄。在准备执行语句时,使用句柄:my $sth = $dbh-&gt;prepare(.....); $sth-&gt;execute(...);
      【解决方案3】:

      您不想存储对从 fetchrow_hashref 返回的 $result 的引用,因为每个后续调用都会覆盖该引用。

      没关系,您在调用 generate_config 时没有使用引用,因为您是按值传递数据。

      您是否在 generate_config 和调用函数中使用相同的 $result 变量?您应该在 generate_config 中使用自己的“我的 $result”。

            while ( my $result = $select->fetchrow_hashref() )
            #       ^^  #add my
      

      这就是您所包含的当前 sn-ps 代码所能说的全部内容。

      一些清理:

      1. 调用 generate_config 时,您是按值传递,而不是按引用传递。这很好。
      2. 您收到 undef 警告,这意味着您正在使用“use strict;”运行。好!
      3. 在函数中创建词法 $result,通过 my.
      4. 虽然 $$hashr{key} 是有效代码,但首选 $hashr->{key}。
      5. 您正在使用 dbh->prepare,不妨使用占位符。

        sub generateConfig {
          my($inName, inPass, $inExt) = @_;
        
          my $goodData = 1;
          my $select   = $dbh->prepare("SELECT id FROM $databasesTableName WHERE name = ?");
          my $insert   = $dbh->prepare("
                            INSERT INTO $configTableName(
                              databaseID
                              ,username
                              ,password
                            ,path) 
                            VALUES( ?, ?, ?, ?)" );
          my $path     = $documentRoot . $inName . "_config." . $inExt;
          $select->execute( $inName );
        
          if ($select->rows < 1 ) {
                $goodData = 0;
          }
        
          while ( my $result = $select->fetchrow_hashref() )
          {
            insert->execute( $result->{id}, $inName, $inPass, $path );
          }
        
         return 1;
        

        }

      【讨论】:

      • 非常感谢。这是我在 generateConfig 函数中再次使用 $result 的事实!我完全错过了这个!我还将实施您建议的其他一些事情。您可能会说,我是 Perl 的新手。再次感谢!另外,谢谢大家,你的帖子也很有帮助!
      猜你喜欢
      • 2016-12-04
      • 2011-02-01
      • 2011-01-17
      • 1970-01-01
      • 2017-03-13
      • 1970-01-01
      • 2017-01-18
      • 2018-02-24
      • 2010-12-21
      相关资源
      最近更新 更多