大骆驼书已经过了两遍,书柜上的一本《Perl 进阶》纯属情怀,中文版,这几天翻阅发现其中的翻译惨不忍睹,语无伦次。
改看 PDF,顺便做笔记
《Intermediate Perl》读书笔记
- PerlMonk
- 渐入佳境
- 帖子: 49
- 注册时间: 2016年09月19日 10:20
- 联系:
《Intermediate Perl》读书笔记
上次由 PerlMonk 在 2017年04月14日 17:04,总共编辑 1 次。
- PerlMonk
- 渐入佳境
- 帖子: 49
- 注册时间: 2016年09月19日 10:20
- 联系:
Re: 《Intermediate Perl》读书笔记
列表操作
- ",", sort,reverse,push, pop, shift, unshift, grep, map
使用 grep 过滤列表
- grep 的使用可以分为表达式形式和 block 形式
筛选大于10的数并保存到另一个数组:结果为 16, 32, 64Code: [show] | [select all]
通过隐式引用来筛选末尾含有4的数字:
my @end_in_4 = grep /4$/, @input_numbers;
如果测试表达式较为复杂,可以写在一个子例程中,然后通过 grep 调用。
在一组数字中,提取个位十位... 相加 %2 余 1 的项:块形式(相比调用子例程的形式,少了 return。在这里使用 return 将退出 grep ):Code: [show] | [select all]Code: [show] | [select all]
- 类似 grep ,但 map 用于转换而不是筛选
以及 map 没有规定对于每一项只返回一个值Code: [show] | [select all]
my @result = map { $_, 3 * $_ } @input_numbers;
借此可以快速从一个列表生成一组哈希映射,以便于做字典判断Code: [show] | [select all]
- grep 的使用可以分为表达式形式和 block 形式
- 捕获错误
- 示例:
其中每一行都有可能出错导致程序崩溃,但在实际应用中并不意味着应该结束整个程序,Perl 通过 eval 实现错误捕获:Code: [show] | [select all]
当 eval 代码块运行出错时,错误信息保存到 $@,eval 之后的代码继续运行。注意 eval 不是结构语句,末尾必须加分号。Code: [show] | [select all]
eval 语句块也可以像函数一样 return,如果出错,返回空值(在标量环境返回 undef,在数组环境返回空列表)。现在可以安全地处理零除错误:
my $average = eval { $total / $count };
$average 要么是"商"要么是"undef"。
注意
Perl 允许 eval 镶嵌使用。
eval 可以捕获一般的错误,但无法处理结束进程、内存溢出等情况
Try::TinyCode: [show] | [select all]
- eval 除了代码块的形式,还有一种字符串形式。在运行时编译运行某段字符串内的代码。这将带来一定风险,或许会执行带有攻击性的代码。
一个简短的示例:
因为 eval 能够返回最后一句代码的结果,所以不必将赋值放在待执行的字符串中Code: [show] | [select all]
和代码块形式一样,如果执行错误,有关信息将保留到 $@:Code: [show] | [select all]>The quotient isCode: [show] | [select all]
>syntax error at (eval 1) line 2, at EOF
提醒
请谨慎使用 eval 执行字符串代码的形式,尽可能使用其他方法达到目的。在11章将介绍如何加载外部文件代码并执行,并使用更好的方法。
- 示例:
- do 是 Perl 语言中一个强有力但容易被忽视的工具,它提供一种方式将一组表达式组织到一个代码块中,
并像子例程一样返回最后执行的结果。
使用 do 语句块简化多个判断和赋值
- 假设要为 $bowler 赋值,但是分为三种条件,需要写出多个 $bowler:
如果改为 do 语句块的形式,只需要一个 $bowlerCode: [show] | [select all]Code: [show] | [select all]
- do 能够创建一个包围作用域,当我们要一次读取整个文件内容到变量中,可以通过 do block 私有作用域,为 $/ 和 @ARGV 创建私有副本,从而能够使用 <> 句柄读取 $filename 参数的文件内容
Code: [show] | [select all]
- 类似 eval,do 也有将字符串作为参数的形式,当传递的是字符串而非代码块时,do 假设传入的是文件,并从文件中读取代码编译执行:
do "slurp.pl";
(类似于 `eval "type slurp.pl";` 但有区别,参考 perldoc -f do)
缺点是:即使执行的代码发生错误,程序仍会继续运行。不仅如此,即使是加载运行过的文件,仍会再次执行(对比 require)。基于这些原因,很少人使用 do 语句
在上一章,我们提到了使用 use 加载模块,以及 use 语句在编译时运行。但还有另一种方式加载模块,即 require ,在运行时加载模块:
require List::Util;
use List::Util 的实质是在 BEGIN 块中执行 require 以及 该模块的 import() 方法;
通常 use 用于导入模块,而 require 还可以用文件名作为参数,导入文件:Code: [show] | [select all]
require $filename;
require 能够记住已经加载过的文件,对于重复的加载将不会再执行 ( 对比 do )。更多内容参考 12 章 - Creating Your Own Perl Distribution
- 假设要为 $bowler 赋值,但是分为三种条件,需要写出多个 $bowler:
上次由 PerlMonk 在 2017年04月17日 13:17,总共编辑 1 次。
- PerlMonk
- 渐入佳境
- 帖子: 49
- 注册时间: 2016年09月19日 10:20
- 联系:
Re: 《Intermediate Perl》读书笔记 - 第五章
第五章 的内容是关于 数组、哈希的引用,这个就比较基础了,以后再整理一份概要。
- PerlMonk
- 渐入佳境
- 帖子: 49
- 注册时间: 2016年09月19日 10:20
- 联系:
《Intermediate Perl》读书笔记 - Chapter 6 操作复杂数据结构(储存、打印)
管理复杂数据结构
- 使用调试器查看数据结构
- 参考 PerlDebug
示例代码:操作示例:Code: [show] | [select all]
在 perlDB 控制台中输入 s 执行下一句,x 后附加变量名显示对应变量的状态perl -d bytecounts.pl Loading DB routines from perl5db.pl version 1.37 Editor support available. Enter h or 'h h' for help, or 'perldoc perldebug' for more help. main::(bytecounts.pl:1): my %total_bytes; DB<1> s main::(bytecounts.pl:2): while (<DATA>) { DB<1> s main::(bytecounts.pl:3): my ($source, $destination, $bytes) = split; DB<1> s main::(bytecounts.pl:4): $total_bytes{$source}{$destination} += $bytes; DB<1> x $source, $destination, $bytes 0 'professor.hut' 1 'gilligan.crew.hut' 2 1250
也可以直接输入代码,查看数组:x @array
, 查看哈希字典:x \%hash
DB<8> @a = (1 .. 3); DB<9> x @a 0 1 1 2 2 3
也可以在 x 后面使用列表、哈希操作符(sort, keys, values ... )DB<10> %h = qw/a 1 b 2 c 3/; DB<12> x \%h 0 HASH(0x2ac9e2c) 'a' => 1 'b' => 2 'c' => 3
一些总结DB<31> %h = qw(a b c d e f); DB<34> x sort keys %h 0 'a' 1 'c' 2 'e'
s [函数名] 进入函数并逐步运行,提示符从DB<>
变为DB<<>>
n [函数名] 执行函数,并且一次执行完。
b [line|event|sub] 添加断点。
B [line|*] 删除断点
w [expr] 监视变量,受监视的变量在变化时将显示到终端,w $var
W [expr|*] 删除变量监视器
p 同 print
S [[!]pat] 枚举当前加载的所有子例程名单,可以设置过滤、排除,例:
y 查看当前脚本的变量列表和对应的值DB<24> S main main::BEGIN main::dumpValue main::dumpvar main::test
c [n] 连续执行代码直到某一行,如果不带参数,会结束当前循环或者脚本。
a [ln]+[cmd] 在某行之前执行命令,例a 8 print "$var\n"
,实测有时候没有效果,最好先为该行设置断点
A [ln|*] 删除命令
- Code: [show] | [select all]
来看另一段代码,@data1 , @data2 互相包含对方的引用,Data::Dumper 能够正确打印他们的结构 注意这里给 Dumper 传入两个数组引用:$VAR1 = { 'thurston.howell.hut' => { 'lovey.howell.hut' => 1250 }, 'ginger.girl.hut' => { 'maryann.girl.hut' => 199, 'professor.hut' => 1218 }, 'professor.hut' => { 'gilligan.crew.hut' => 1250, 'lovey.howell.hut' => 1360 } };
Code: [show] | [select all]
如果使用 Perl Debugger$VAR1 = [ 'one', 'won', [ 'two', 'too', 'to', [] ] ]; $VAR1->[2][3] = $VAR1; $VAR2 = $VAR1->[2];
Data::DumpDB<2> x \@data1, \@data2 0 ARRAY(0x24a4e84) 0 'one' 1 'won' 2 ARRAY(0x47f324) 0 'two' 1 'too' 2 'to' 3 ARRAY(0x24a4e84) -> REUSED_ADDRESS 1 ARRAY(0x47f324) -> REUSED_ADDRESS
如果不介意数据的建,可以考虑使用 Data::Dump,输出相对简洁:Code: [show] | [select all]
Data::Printer{ "ginger.girl.hut" => { "maryann.girl.hut" => 199, "professor.hut" => > 1218 }, "professor.hut" => { "gilligan.crew.hut" => 1250, "lovey.howell.hut" > => 1360 }, "thurston.howell.hut" => { "lovey.howell.hut" => 1250 }, }
这个模块在 ActivePerl V5.16 ppm 安装失败,但是可以从CPAN下载安装,另外还依赖 Sort::Naturally, Clone::PP
Code: [show] | [select all]{ ginger.girl.hut { maryann.girl.hut 199, professor.hut 1218 }, professor.hut { gilligan.crew.hut 1250, lovey.howell.hut 1360 }, thurston.howell.hut { lovey.howell.hut 1250 } }
- 参考 PerlDebug
在线用户
正浏览此版面之用户: Ahrefs [Bot] 和 0 访客