【问题标题】:Problems with Keys in Hash哈希中的键问题
【发布时间】:2013-12-30 20:45:50
【问题描述】:

在将我的脚本从 Windows 机器移动到 Unix 系统后,我遇到了一个非常奇怪的问题。 我已经编写了 READIN 子程序,并在 Windows 上使用 Perl 5.16.3 成功对其进行了测试,但它在使用 Perl 5.14.2 的 Unix 下无法运行

sub READIN
{
my (%tmp, $val, $key);
open (DAT, "$_[0]")or die "Thou shalt not open this file, so I generated an error: $! \n";
while (<DAT>)
    {
    chomp;
    ($val, $key) = split (/;/);
    #print "Value -> $val - Key_for_Hash -> $key\n"; *#DBG - Works!*

    $tmp{$key} = exists $tmp{$key}? "$val" : $val;

    #print "ValueH -> $tmp{$key} - Key_for_HashH -> $key\n"; *#DBG - Works!*

    #print "KeyH-> $key - ValueH -> $tmp{$key}\n"; *#DBG - doesn't work, cuts of everything before " - ValueH....."*

    #print "Value2 -> $val - Key_for_Hash2 -> $key\n\n";*#DBG - Works!*

    }
close DAT or die "Filehandle is grumpy today and dislikes your Idea to be closed as of $\n";
return %tmp;
}

我使用 Data::Dumper 得到的输出是这样的:

    $VAR1 = {
' => '18.15.7.1.39.',
' => '19.15.7.1.39.',
' => '19.15.9.1.6.1.',
' => '19.15.7.1.6.',
' => '19.15.1.',
' => '18.15.1.',
' => '18.15.7.1.36.',
' => '18.15.7.1.34.',
' => '18.15.7.1.1.',
' => '18.15.7.1.33.',
' => '18.1.9.0',
' => '19.15.7.1.36.',
' => '16.15.2.1.4.1',
' => '18.15.7.1.38.',
' => '19.15.9.1.13.',
' => '18.15.9.1.6.1.',
' => '16.1.9.0',
' => '19.15.7.1.33.',
' => '19.15.7.1.37.',
' => '19.1.9.0',
' => '19.15.9.1.3.',e
' => '19.15.7.1.4.',
' => '19.15.7.1.38.',
' => '19.15.7.1.34.',
          'radioid2e' => '19.15.7.1.1.',
' => '16.15.2.1.4.1',
' => '19.15.7.1.35.',
' => '18.15.7.1.35.'
        };

最后,这是我从文件中读取的数据:

16.1.9.0;摆脱
16.15.2.1.4.1;卡普
16.15.2.1.4.1;模组
18.1.9.0;rid2
18.15.7.1.35.;tdmkapt2
18.15.7.1.38.;tdmkapr2
18.15.7.1.34.;modt2
18.15.7.1.33.;modr2
18.15.9.1.6.1.;tdmkap2
18.15.7.1.36.;etht2
18.15.7.1.39.;ethr2
18.15.1.;rt2
18.15.7.1.1.;radioid2
19.1.9.0;rid2e
19.15.7.1.35.;tdmkapt2e
19.15.7.1.38.;tdmkapr2e
19.15.7.1.34.;modt2e
19.15.7.1.33.;modr2e
19.15.9.1.6.1.;tdmkap2e
19.15.7.1.36.;etht2e
19.15.7.1.39.;ethr2e
19.15.1.;rt2e
19.15.7.1.4.;um2e
19.15.7.1.37.;lm2e
19.15.9.1.3.;glokapam2e
19.15.9.1.13.;ethkapam2e
19.15.7.1.6.;acmcpm
19.15.7.1.1.;radioid2e

有人能指出我做错了什么吗?还是 5.14.6 上的普遍问题?

//编辑:

这是我将在 Windows (Perl 5.16.3) 中得到的 Data::Dumper 输出:

$VAR1 = {
      'rid2e' => '19.1.9.0',
      'rt2' => '18.15.1.',
      'ethkapam2e' => '19.15.9.1.13.',
      'etht2' => '18.15.7.1.36.',
      'etht2e' => '19.15.7.1.36.',
      'tdmkapt2e' => '19.15.7.1.35.',
      'tdmkapr2' => '18.15.7.1.38.',
      'tdmkapt2' => '18.15.7.1.35.',
      'ethr2' => '18.15.7.1.39.',
      'ethr2e' => '19.15.7.1.39.',
      'tdmkap2e' => '19.15.9.1.6.1.',
      'acmcpm' => '19.15.7.1.6.',
      'rt2e' => '19.15.1.',
      'modt2e' => '19.15.7.1.34.',
      'modr2e' => '19.15.7.1.33.',
      'um2e' => '19.15.7.1.4.',
      'radioid2' => '18.15.7.1.1.',
      'tdmkap2' => '18.15.9.1.6.1.',
      'rid' => '16.1.9.0',
      'modr2' => '18.15.7.1.33.',
      'glokapam2e' => '19.15.9.1.3.',
      'rid2' => '18.1.9.0',
      'kap' => '16.15.2.1.4.1',
      'tdmkapr2e' => '19.15.7.1.38.',
      'radioid2e' => '19.15.7.1.1.',
      'modt2' => '18.15.7.1.34.',
      'mod' => '16.15.2.1.4.1',
      'lm2e' => '19.15.7.1.37.'
    };

【问题讨论】:

  • 您所期望的输出应该是什么样子并不明显,您能更好地解释一下吗?
  • 我希望对应值的键也应该在输出中,就像这一行 'radioid2e' =&gt; '19.15.7.1.1.', 一样,当然只有不同的数据

标签: perl file hash key


【解决方案1】:

看起来你有一个\r\n 行结尾。而不是chomp,您可以尝试使用

s/[\r\n]+$//g;

这是从其他操作系统(例如 Windows)导入文件时的常见问题。 chomp 命令从行尾删除本机换行符(包含在变量$/ 中)。在 linux 中,这将是 \n,但在 Windows 中,它是 \r\n。所以在linux中,你读到\n的一行,删除\n\r将光标重置到行首,这样行首就被覆盖了。

实际上,这主要是一个视觉问题(除了字符串中有垃圾\r 字符)。如果你添加

$Data::Dumper::Useqq = 1;

在您的代码中,您将看到以纯文本形式打印出的 \r 字符,如下所示:

"ethr2\r" => "18.15.7.1.39.",

您还应该了解以下内容:

  • 始终使用use strict; use warnings;。它比您可能在代码中使用的任何其他东西都能为您提供更多帮助,而且学习使用它们并不难。
  • $tmp{$key} = exists $tmp{$key}? "$val" : $val; 什么都不做,因为 "$val"$val 是相同的。如果您有use warnings,它会在密钥不存在时发出警告,并发出警告Use of uninitialized value $val in string
  • 由于您希望拆分超过 2 次的可能性不大,您不妨对拆分使用限制:split /;/, $_, 2;

【讨论】:

  • $/有意义吗?
  • @mpapec 有多种解决方案可以更改为适合 CRLF 文件的硬编码解决方案,但我总是发现问题在于人们的文件各不相同,因此硬编码解决方案并不可取。跨度>
  • 啊,所以实际上他的其余代码确实可以正常工作,但是键是不可见的,因为打印 \r 会将光标返回到行首。棘手。
  • 这正是问题所在,我不会在几天内找到这个...我刚刚更正了读取的数据(因为这些是静态“配置”文件)但是你能解释一下吗我怎么能用 s/[\r\n]+$//g; 交换 chomp 命令?
  • @user2982931 这是从其他操作系统(例如 Windows)导入文件时的常见问题。 chomp 命令从行尾删除本机换行符(包含在变量 $/ 中)。在 linux 中,这将是 \n,但在 Windows 中,它是 \r\n。所以在linux中,你读到\n的一行,删除\n\r将光标重置到行首,这样行首就被覆盖了。
猜你喜欢
  • 2011-04-27
  • 2013-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多