Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1818688
  • 博文数量: 145
  • 博客积分: 8668
  • 博客等级: 中将
  • 技术积分: 3911
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-09 21:21
个人简介

work hard

文章分类

全部博文(145)

文章存档

2016年(1)

2015年(1)

2014年(1)

2013年(12)

2012年(3)

2011年(9)

2010年(34)

2009年(55)

2008年(20)

2007年(9)

分类: LINUX

2011-05-08 15:01:02

Perl 中的调试方法

本文属个人原创,欢迎自由转载。但请标明本文的连接,并保证本文的完整性。
Godbach
2011/05/07

本文的阅读群体定位在 Perl 新手,高手可以直接忽略。:-)

很多编程工具最常用的调试方法都是在一些环节打印出一些信息,然后去判断是否符合预期。比如 C 中 printf,kernel 中 printk。当然,Perl 也不例外,可以用 print 打印消息。
但是,这里我并不是要介绍 print。否则,各位看官除了不屑之外,只有鄙视啦。

这里要介绍两个用于调试的模块: 一个是 Data::Dumper,另一个是 Smart::Comments。且看这两个模块是如何用于调试的。

1. Data::Dumper
一看到有 Dumper 字样,是不是就联想到了 C 中的 coredump,想到了抓包常用的 tcpdump,想到了直接查看文件 16 进制的 hexdump,以及其他一些具有 dump 功能的工具了。
想到了这些,可能就会感觉但凡是带着 dump 字样的东东应改都比较牛叉吧。实际上是不是如此呢,下面咱们就通过实例来说明。
如果大家的环境中还没有安装 Data::Dumper,那就通过 cpan 安装一个包。有网络环境就是好啊,一个命令敲下去,一会儿模块就安装好了,就可以练兵了。

实例如下(dumper.pl):

  1. #!/usr/bin/perl
  2. # Godbach, 2011/05/07
  3. use warnings;
  4. use strict;
  5. use Data::Dumper;

  6. my $var = "Hello, world";
  7. my @arr = qw(hello world bye bye);
  8. my %foo = (
  9.     name => 'zhangsan',
  10.     age => '28',
  11.     sx => 'male',
  12.     company => {
  13.         'intel' => '2',
  14.         'ibm' => '3',
  15.         'microsoft' => '2'
  16.     },
  17. );

  18. # 打印变量
  19. print "==> Dump Variable:\n";
  20. print Dumper($var);

  21. # 打印数组
  22. print "==> Dump Array:\n";
  23. print Dumper(@arr);

  24. # 打印数组引用
  25. print "==> Dump Array ref:\n";
  26. print Dumper(\@arr);

  27. # 打印 hash
  28. print "==> Dump Hash:\n";
  29. print Dumper(%foo);

  30. # 打印 hash 引用
  31. print "==> Dump Hash ref:\n";
  32. print Dumper(\%foo);

  33. # 打印子 hash
  34. print "==> Dump Sub Hash\n";
  35. print Dumper($foo{company});


  36. exit 0;


该程序使用 Dumper 模块,打印出了 Perl 普通变量、数组、数组引用、hash、hash 引用以及子 hash 的内容。
程序执行结果如下:
[root@Godbach Perl]# ./dumper.pl
==> Dump Variable:
$VAR1 = 'Hello, world';
==> Dump Array:
$VAR1 = 'hello';
$VAR2 = 'world';
$VAR3 = 'bye';
$VAR4 = 'bye';
==> Dump Array ref:
$VAR1 = [
          'hello',
          'world',
          'bye',
          'bye'
        ];
==> Dump Hash:
$VAR1 = 'name';
$VAR2 = 'zhangsan';
$VAR3 = 'company';
$VAR4 = {
          'ibm' => '3',
          'microsoft' => '2',
          'intel' => '2'
        };
$VAR5 = 'sx';
$VAR6 = 'male';
$VAR7 = 'age';
$VAR8 = '28';
==> Dump Hash ref:
$VAR1 = {
          'name' => 'zhangsan',
          'company' => {
                         'ibm' => '3',
                         'microsoft' => '2',
                         'intel' => '2'
                       },
          'sx' => 'male',
          'age' => '28'
        };
==> Dump Sub Hash
$VAR1 = {
          'ibm' => '3',
          'microsoft' => '2',
          'intel' => '2'
        };


从输出结果中,可以看出:
(1)Dumper 最简单的用法,就是将你需要打印的元素传递给 Dumper() 函数即可,同时调用 print 输出结果。
(2)Dumper 打印的结果中所有变量都按照自己的方法进行命名,缺省按照 $VAR1 开始。
(3)在数组和 hash 的打印中,传递数组或 hash 的引用,Dumper 输出的结果会更加容易阅读。可以参见上面输出结果中 Dump Arrary ref 和 Dump Hash ref 部分的结果和直接打印的结果作对比。

总之,Dumper 可以将我们所关心的内容完成的打印出来,让你觉得有问题的地方无所遁逃。
这里只是简单说明 Dumper 的用法,更多的使用细节请通过 perldoc Data::Dumper 查看对应的手册。

2. Smart::Comments
这个模块有个 Smart 字样,表面看起来应该是有比较智能的。且后面看一下有何 Smart 之处。
还是直接上例子吧,详细的使用方法看手册,这里只是展示一下这个模块的简单用法。更多牛叉的细节,还是需要自己实践中挖掘和发现。

笔者是懒人一个,因此还是用上面 dumper.pl 例程中的主题部分,将调用 Dumper 的地方换成 Smart::Comments 所对应的即可。所要打印的内容仍然是包含变量、数组、数组引用、hash、hash 引用和子 hash。

代码如下:

  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;
  4. use Smart::Comments;

  5. my $var = "Hello, world";
  6. my @arr = qw(hello world bye bye);
  7. my %foo = (
  8.     name => 'zhangsan',
  9.     age => '28',
  10.     sx => 'male',
  11.     company => {
  12.         'intel' => '2',
  13.         'ibm' => '3',
  14.         'microsoft' => '2'
  15.     },
  16. );

  17. ### $var

  18. ### @arr

  19. ### arr: \@arr

  20. ### %foo

  21. ### foo: \%foo

  22. ### co: $foo{company}

  23. exit 0;


当 use Smart::Comments 时,代码中 '###' 就相当于提示这里要打印信息。要打印的内容,就是 '###' 这个后面的表达式。

运行一把看结果:
[root@Godbach Perl]# ./smart_comments.pl  

### $var: 'Hello, world'

### @arr: [
###         'hello',
###         'world',
###         'bye',
###         'bye'
###       ]

### \@arr

### %foo: {
###         age => '28',
###         company => {
###                      ibm => '3',
###                      intel => '2',
###                      microsoft => '2'
###                    },
###         name => 'zhangsan',
###         sx => 'male'
###       }



### \%foo

### $foo{company}


从这个结果我们可以看出:
(1)不管是变量、数组还是 hash,打印的时候都可以显示对应的名字,这个比 Dumper 的 $VAR1...$VARn 更加易读一些吧。
(2)所有打印出来的信息开头三个字符都是 '#'。这个就算你不小心将此调试信息留在代码中了,而且最终和程序的正常输出混在一起了,简单通过 '###' 也可以区分出来。
(3)这一点应该从代码中看不出来,要看手册。:-)。当把程序调试通过之后,只需通过把代码开头的 use Smart::Comments 注释掉,或者改成 no Smart::Comments 就可以让程序不在输出调试信息。这一点是不是比较爽啊,解除了删除调试信息的苦恼。
(4)是不是发现了,代码中数组的引用、 hash 的引用、子 hash 都没有正确的输出结果,原封不动的把代码输出出来了。这会不会是我们的用法不对,还是我们的用法不对呢。
经过咨询有经验的高手,原来是这种情形需要在前面加个名字,至于什么名字,随意就好了。但是名字后面要跟着':'。对于几个引用和子 hash 修改后的代码如下:


  1. ### $var

  2. ### @arr

  3. ### arr: \@arr

  4. ### %foo

  5. ### foo: \%foo


然后再查看一下执行结果:
[root@Godbach Perl]# ./smart_comments.pl  

### $var: 'Hello, world'

### @arr: [
###         'hello',
###         'world',
###         'bye',
###         'bye'
###       ]

### arr: [
###        'hello',
###        'world',
###        'bye',
###        'bye'
###      ]

### %foo: {
###         age => '28',
###         company => {
###                      ibm => '3',
###                      intel => '2',
###                      microsoft => '2'
###                    },
###         name => 'zhangsan',
###         sx => 'male'
###       }

### foo: {
###        age => '28',
###        company => {
###                     ibm => '3',
###                     intel => '2',
###                     microsoft => '2'
###                   },
###        name => 'zhangsan',
###        *** => 'male'
###      }

### co: {
###       ibm => '3',
###       intel => '2',
###       microsoft => '2'
###     }


OK。 修改之后就可以正常输出了。至于为什么需要处理,查一下相关的文档吧。

至此,笔者简单介绍了 Perl 中用于调试的两个模块,而且都是简单的介绍。再次强调,要想了解全部的功能,还是要去看文档的。
至于这两个模块哪个好用,见仁见智。用一句流行的说法:适合自己的就是最好的。


阅读(3167) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~