《Perl语言入门》——读书笔记

2023-03-06 13:26:57 浏览数 (2)

Perl语言入门 /** * prism.js Github theme based on GitHub's theme. * @author Sam Clarke */ code[class*="language-"], pre[class*="language-"] { color: #333; background: none; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.4; -moz-tab-size: 8; -o-tab-size: 8; tab-size: 8; -webkit-hyphens: none; -moz-hyphens: none; -ms-hyphens: none; hyphens: none; } /* Code blocks */ pre[class*="language-"] { padding: .8em; overflow: auto; /* border: 1px solid #ddd; */ border-radius: 3px; /* background: #fff; */ background: #f5f5f5; } /* Inline code */ :not(pre) > code[class*="language-"] { padding: .1em; border-radius: .3em; white-space: normal; background: #f5f5f5; } .token.comment, .token.blockquote { color: #969896; } .token.cdata { color: #183691; } .token.doctype, .token.punctuation, .token.variable, .token.macro.property { color: #333; } .token.operator, .token.important, .token.keyword, .token.rule, .token.builtin { color: #a71d5d; } .token.string, .token.url, .token.regex, .token.attr-value { color: #183691; } .token.property, .token.number, .token.boolean, .token.entity, .token.atrule, .token.constant, .token.symbol, .token.command, .token.code { color: #0086b3; } .token.tag, .token.selector, .token.prolog { color: #63a35c; } .token.function, .token.namespace, .token.pseudo-element, .token.class, .token.class-name, .token.pseudo-class, .token.id, .token.url-reference .token.variable, .token.attr-name { color: #795da3; } .token.entity { cursor: help; } .token.title, .token.title .token.punctuation { font-weight: bold; color: #1d3e81; } .token.list { color: #ed6a43; } .token.inserted { background-color: #eaffea; color: #55a532; } .token.deleted { background-color: #ffecec; color: #bd2c00; } .token.bold { font-weight: bold; } .token.italic { font-style: italic; } /* JSON */ .language-json .token.property { color: #183691; } .language-markup .token.tag .token.punctuation { color: #333; } /* CSS */ code.language-css, .language-css .token.function { color: #0086b3; } /* YAML */ .language-yaml .token.atrule { color: #63a35c; } code.language-yaml { color: #183691; } /* Ruby */ .language-ruby .token.function { color: #333; } /* Markdown */ .language-markdown .token.url { color: #795da3; } /* Makefile */ .language-makefile .token.symbol { color: #795da3; } .language-makefile .token.variable { color: #183691; } .language-makefile .token.builtin { color: #0086b3; } /* Bash */ .language-bash .token.keyword { color: #0086b3; } /* highlight */ pre[data-line] { position: relative; padding: 1em 0 1em 3em; } pre[data-line] .line-highlight-wrapper { position: absolute; top: 0; left: 0; background-color: transparent; display: block; width: 100%; } pre[data-line] .line-highlight { position: absolute; left: 0; right: 0; padding: inherit 0; margin-top: 1em; background: hsla(24, 20%, 50%,.08); background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); pointer-events: none; line-height: inherit; white-space: pre; } pre[data-line] .line-highlight:before, pre[data-line] .line-highlight[data-end]:after { content: attr(data-start); position: absolute; top: .4em; left: .6em; min-width: 1em; padding: 0 .5em; background-color: hsla(24, 20%, 50%,.4); color: hsl(24, 20%, 95%); font: bold 65%/1.5 sans-serif; text-align: center; vertical-align: .3em; border-radius: 999px; text-shadow: none; box-shadow: 0 1px white; } pre[data-line] .line-highlight[data-end]:after { content: attr(data-end); top: auto; bottom: .4em; }html body{font-family:"Helvetica Neue",Helvetica,"Segoe UI",Arial,freesans,sans-serif;font-size:16px;line-height:1.6;color:#333;background-color:#fff;overflow:initial;box-sizing:border-box;word-wrap:break-word}html body>:first-child{margin-top:0}html body h1,html body h2,html body h3,html body h4,html body h5,html body h6{line-height:1.2;margin-top:1em;margin-bottom:16px;color:#000}html body h1{font-size:2.25em;font-weight:300;padding-bottom:.3em}html body h2{font-size:1.75em;font-weight:400;padding-bottom:.3em}html body h3{font-size:1.5em;font-weight:500}html body h4{font-size:1.25em;font-weight:600}html body h5{font-size:1.1em;font-weight:600}html body h6{font-size:1em;font-weight:600}html body h1,html body h2,html body h3,html body h4,html body h5{font-weight:600}html body h5{font-size:1em}html body h6{color:#5c5c5c}html body strong{color:#000}html body del{color:#5c5c5c}html body a:not([href]){color:inherit;text-decoration:none}html body a{color:#08c;text-decoration:none}html body a:hover{color:#00a3f5;text-decoration:none}html body img{max-width:100%}html body>p{margin-top:0;margin-bottom:16px;word-wrap:break-word}html body>ul,html body>ol{margin-bottom:16px}html body ul,html body ol{padding-left:2em}html body ul.no-list,html body ol.no-list{padding:0;list-style-type:none}html body ul ul,html body ul ol,html body ol ol,html body ol ul{margin-top:0;margin-bottom:0}html body li{margin-bottom:0}html body li.task-list-item{list-style:none}html body li>p{margin-top:0;margin-bottom:0}html body .task-list-item-checkbox{margin:0 .2em .25em -1.8em;vertical-align:middle}html body .task-list-item-checkbox:hover{cursor:pointer}html body blockquote{margin:16px 0;font-size:inherit;padding:0 15px;color:#5c5c5c;background-color:#f0f0f0;border-left:4px solid #d6d6d6}html body blockquote>:first-child{margin-top:0}html body blockquote>:last-child{margin-bottom:0}html body hr{height:4px;margin:32px 0;background-color:#d6d6d6;border:0 none}html body table{margin:10px 0 15px 0;border-collapse:collapse;border-spacing:0;display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all}html body table th{font-weight:bold;color:#000}html body table td,html body table th{border:1px solid #d6d6d6;padding:6px 13px}html body dl{padding:0}html body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:bold}html body dl dd{padding:0 16px;margin-bottom:16px}html body code{font-family:Menlo,Monaco,Consolas,'Courier New',monospace;font-size:.85em !important;color:#000;background-color:#f0f0f0;border-radius:3px;padding:.2em 0}html body code::before,html body code::after{letter-spacing:-0.2em;content:"0a0"}html body pre>code{padding:0;margin:0;font-size:.85em !important;word-break:normal;white-space:pre;background:transparent;border:0}html body .highlight{margin-bottom:16px}html body .highlight pre,html body pre{padding:1em;overflow:auto;font-size:.85em !important;line-height:1.45;border:#d6d6d6;border-radius:3px}html body .highlight pre{margin-bottom:0;word-break:normal}html body pre code,html body pre tt{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}html body pre code:before,html body pre tt:before,html body pre code:after,html body pre tt:after{content:normal}html body p,html body blockquote,html body ul,html body ol,html body dl,html body pre{margin-top:0;margin-bottom:16px}html body kbd{color:#000;border:1px solid #d6d6d6;border-bottom:2px solid #c7c7c7;padding:2px 4px;background-color:#f0f0f0;border-radius:3px}@media print{html body{background-color:#fff}html body h1,html body h2,html body h3,html body h4,html body h5,html body h6{color:#000;page-break-after:avoid}html body blockquote{color:#5c5c5c}html body pre{page-break-inside:avoid}html body table{display:table}html body img{display:block;max-width:100%;max-height:100%}html body pre,html body code{word-wrap:break-word;white-space:pre}}.markdown-preview{width:100%;height:100%;box-sizing:border-box}.markdown-preview .pagebreak,.markdown-preview .newpage{page-break-before:always}.markdown-preview pre.line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}.markdown-preview pre.line-numbers>code{position:relative}.markdown-preview pre.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:1em;font-size:100%;left:0;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.markdown-preview pre.line-numbers .line-numbers-rows>span{pointer-events:none;display:block;counter-increment:linenumber}.markdown-preview pre.line-numbers .line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}.markdown-preview .mathjax-exps .MathJax_Display{text-align:center !important}.markdown-preview:not([for="preview"]) .code-chunk .btn-group{display:none}.markdown-preview:not([for="preview"]) .code-chunk .status{display:none}.markdown-preview:not([for="preview"]) .code-chunk .output-div{margin-bottom:16px}.scrollbar-style::-webkit-scrollbar{width:8px}.scrollbar-style::-webkit-scrollbar-track{border-radius:10px;background-color:transparent}.scrollbar-style::-webkit-scrollbar-thumb{border-radius:5px;background-color:rgba(150,150,150,0.66);border:4px solid rgba(150,150,150,0.66);background-clip:content-box}html body[for="html-export"]:not([data-presentation-mode]){position:relative;width:100%;height:100%;top:0;left:0;margin:0;padding:0;overflow:auto}html body[for="html-export"]:not([data-presentation-mode]) .markdown-preview{position:relative;top:0}@media screen and (min-width:914px){html body[for="html-export"]:not([data-presentation-mode]) .markdown-preview{padding:2em calc(50% - 457px 2em)}}@media screen and (max-width:914px){html body[for="html-export"]:not([data-presentation-mode]) .markdown-preview{padding:2em}}@media screen and (max-width:450px){html body[for="html-export"]:not([data-presentation-mode]) .markdown-preview{font-size:14px !important;padding:1em}}@media print{html body[for="html-export"]:not([data-presentation-mode]) #sidebar-toc-btn{display:none}}html body[for="html-export"]:not([data-presentation-mode]) #sidebar-toc-btn{position:fixed;bottom:8px;left:8px;font-size:28px;cursor:pointer;color:inherit;z-index:99;width:32px;text-align:center;opacity:.4}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] #sidebar-toc-btn{opacity:1}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc{position:fixed;top:0;left:0;width:300px;height:100%;padding:32px 0 48px 0;font-size:14px;box-shadow:0 0 4px rgba(150,150,150,0.33);box-sizing:border-box;overflow:auto;background-color:inherit}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar{width:8px}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar-track{border-radius:10px;background-color:transparent}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar-thumb{border-radius:5px;background-color:rgba(150,150,150,0.66);border:4px solid rgba(150,150,150,0.66);background-clip:content-box}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc a{text-decoration:none}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc ul{padding:0 1.6em;margin-top:.8em}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc li{margin-bottom:.8em}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc ul{list-style-type:none}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview{left:300px;width:calc(100% - 300px);padding:2em calc(50% - 457px - 150px);margin:0;box-sizing:border-box}@media screen and (max-width:1274px){html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview{padding:2em}}@media screen and (max-width:450px){html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview{width:100%}}html body[for="html-export"]:not([data-presentation-mode]):not([html-show-sidebar-toc]) .markdown-preview{left:50%;transform:translateX(-50%)}html body[for="html-export"]:not([data-presentation-mode]):not([html-show-sidebar-toc]) .md-sidebar-toc{display:none} /* Please visit the URL below for more information: */ /* https://shd101wyy.github.io/markdown-preview-enhanced/#/customize-css */

h1 { text-align: center } h2 { text-align: center }

作者:王鸿奇 邮箱:yilupiaoxuewhq@163.com


目录

  • 前言
  • 问题
  • 建议和总结
  • 书籍
  • 站点
  • 特殊变量
  • 第一章 简介
  • 第二章 标量数据
  • 第三章 列表与数组
    • 概念
    • pop、push
    • shift、unshift
    • splice
    • foreach
    • reverse
    • sort
    • each
  • 第四章 子程序
    • 格式
    • 调用子程序
    • 返回值
    • 私有变量/词法变量
  • 第五章 输入与输出
    • 行输入操作符
    • 钻石操作符
    • 文件句柄
    • 其他综述
  • 第六章 hash
  • 第七章 漫游正则表达式王国
    • Unicode属性
    • 量词
    • 分组
    • 多选结构
    • 字符集
    • 其他综述
  • 第八章 用正则表达式进行匹配
    • 匹配操作符:m
    • 模式匹配修饰符
    • 锚位
    • 绑定操作符:=~
    • 捕获
    • 优先级
    • 其他综述
  • 第九章 用正则表达式处理文本
    • s/pattern/replace/modifier
    • 非贪婪模式(?)
    • 分离字符串:split
    • 将列表拼接为字符串:join
    • 其他综述
  • 第十章 其他控制结构
    • if
    • unless
    • while
    • until
    • 裸块控制结构
    • 自增域自减: —
    • for
    • foreach域for的关系
    • 循环控制
    • 条件操作符 "?:"
    • 逻辑运算发 "and && or ||"
    • 短路操作符
  • 十一章 Perl模块
    • 模块来源
    • 安装模块
    • 使用模块
    • 处理文件名 File::Basename
    • 路径名拼接 File:Spec
    • 更友好的处理路径 PATH::Class
    • CGI
    • 数据库接口 DBI
    • 处理日期和时间 DateTime
    • Time::Piece
  • 第十二章 文件测试
    • 测试操作符
    • stat和lstat函数
    • localtime和gmtime
    • 位运算符
  • 十三章 目录操作符
    • chdir
    • 文件名通配符
    • 目录句柄 opendir readdir closedir
    • 递归访问目录 File::Find
    • 删除文件 unlink
    • 重命名/移动文件 rename
    • 链接 link symlink readlink
    • 创建/删除目录 mkdir rmdir File::Temp File::Path
    • 修改权限 chmod File::chmod
    • 修改隶属关系 chown
    • 修改时间戳 utime
  • 第十四章 查找子字符串
    • 查找字符串 index
    • 反向查找字符串 rindex
    • 操作字符串 substr
    • 格式化字符串 sprintf
    • 排序 sort
  • 第十五章 智能匹配与given-when结构
  • 第十六章 进程管理
    • system
    • Unix中,退出值0表示正常,非0表示有问题
    • 环境变量:%ENV
    • exec
    • 反引号
    • qx
    • IPC::System::Simple
    • 通过文件句柄执行外部进程
    • fork exec waitpid
    • 信号、kill
  • 第十七章 高级Perl技巧
    • 切片
    • eval
    • Try::Tiny
    • grep
    • map
    • List::Util

前言


问题

  • 如何卸载包?
    1. % cpan install App::cpanminus
    2. % cpanminus --uninstall Module::Name
  • EBCDIC字符集是什么

建议和总结

关于学习编程语言,再次我将提几个建议:

  1. 无论你此时此刻学的是何种语言,但都要记住一点,学会看文档,无论官网的document,还是系统下的manpage,还是语言或工具独有的help,比如Linux/Unix的man,python中的help和dir,命令行工具中的–help和-h,你都必须学会看,因为那里有最权威最准确最详细的解释。
  2. 先选一种好的开始,再选一本好的书籍,最后再茁壮成长
    • 好的开始:如果你要学的一门语言较难,或者你没有编程经验,那么最好的方法是通过阅读一本较为简单的书籍,或是看一个较为入门的视频,或是参加一场短周期的培训。(内容基础,样例充足,但不能影响对一门语言的整体认识,涉及到应有的语法知识,基本变量和常用函数)。
    • 好的书籍:其实认真学完一本经典书籍就足以让你得心应手了,所以挑一本经典书籍,学后数日乃至数周都将其思想反复琢磨参透便够。
    • 茁壮成长:无论是你的教师还是书籍,亦或是视频都只能作为你的引路者,路最终如何走,走得如何还是得看你自己。当然,如果你到了这一步后,你会发现你已经看透计算机的真面目,你会像欣赏落日余晖般沉醉:你说不出哪里好,但就是喜欢。
  3. 学时记录疑问(标记和简短的描述,不要让其打断学习节奏),学后总结汇总。
  4. 脑子不是用来记忆的,计算机不是用来好奇的。如果要我把人脑和计算机做个比喻,现在我喜欢如此描述: 脑子是CPU的一级缓存(内存小,速度快),计算机是CPU的二级/三级缓存以及内存和磁盘。 所以脑子只适合用来思考,用来缓存常用数据和存储记录了低级缓存索引/摘要的目录页。 请解放你的大脑,让它回到该有的地方。不要再去强调记忆,让计算机服务于我们才是程序员应有个的态度。 专注,专注,再专注。让高级神经里的有限精力都专注于一件事上,打开生物所谓的涌流状态,进入真正意义上的高速运转吧。

书籍

  • 《Programming Perl》:Perl语言编程
  • 《Intermediate Perl》
  • 《Mastering Perl》
  • 《Effective Perl Programming》 # Perl高效编程
  • 《Learning Perl Student Workbook》
  • 《Perl 5 Pocket Reference》
  • 《Mastering Regular Expressions》 – Jeffrey Friedl(O'Reilly):精通正则表达式
  • 《Programming the Perl DBI》 – Alligator Descartes & Time Bunce(O'Reilly):DBI,数据库接口

站点

  • 源码下载
  • CPAN
  • https://www.pm.org
  • Perl核心文档
  • Perl FAQ
  • https://learn.perl.org
  • Perl package manager
  • DBI,数据库接口

特殊变量

具体查看perlvar文档

变量

描述

$!

可读的系统错误信息

$#array

数组长度

$_

默认变量

$^R

内嵌代码的运行结果

$"

字符串中的数组内插的分隔符,默认为空格

$ARGV

当前蒸菜处理的文件

@ARGV

可执行程序的参数列表

$$

进程标识

$?

进程结束时的返回值

%SIG

信号处理函数,key是信号名(非前缀,如INT),value是信号处理函数

$@

eval的返回值

$0

子程序名

$|

缓冲设置

%ENV

环境变量

$^I

备份<>操作符操作的文件,该文件的后缀为$^I的值(默认不备份)

$`

正则匹配区段前的内容

$&

正则匹配区段的内容

$'

正则匹配区段后的内容

$^N, $

编号最小和最大的捕获内容

%

命名捕获组

@_

子程序的参数列表


第一章 简介

  • 反引号:调用外部命令,可获取返回值 @lines = `perldoc -u -fatans`

第二章 标量数据

  • 数字总是按“双精度浮点数”来保存并运算的。
  • 允许在整数直接量中插入下划线,便于阅读:61_284_042_283_586
  • 乘幂:
    • 2的3次方:2**3
  • “无内置限制”原则:可以填满内存
  • 在源码中使用Unicode编码:use utf8;
  • 单引号:直接量,除了单引号和反斜杠外的字符都是本身
  • 双引号:直接量,支持变量内插,支持转义字符 o 转义字符描述 n换行 r回车 t水平制表符 f换页符 b退格 a系统响铃 eESC(ASCII编码的转义字符) 07八进制标识的ASCII值 x7f十六机制标识的ASCII x{2744}十六进制标识的Unicode代码点 cC控制符,也就是Control键的代码(此例表示Ctrl键和C键的返回码) \反斜杠 "双引号 l将下个字母转为小写 L将它后面的所有字母都转为小写的,直到E为止 u将下个字母转为大写 U将它后面的所有字母都转为大写的,直到E为止 Q相当于把它到E之间的非单词(non word)字符加上反斜线转义 E结束L、U、Q开始的作用范围
  • 连接字符串:
    • "helloword":"hello" . "world"
  • 重复字符串
    • "haha":"ha" x 2
  • 数字与字符串之间自动转换
  • 内置警告信息
    • % perl -w my_program
    • use warnings;
    • #! /usr/bin/perl -w
    • 详细的信息:use diagnostics;
    • 详细的信息:% perl -W my_program
  • 变量:存储一个或多个的得容器的名称。 标量变量:单单存储一个值得变量。符号意为“取标量”,variable 内插时可用花括号来限定名称范围:print "Hi
  • 双目运算符: =.=/=*=**=等等
  • 代码点
    • chr():代码转字符,$alef = chr( 0x05D0 )
    • ord():字符转代码点,$code_point = ord('?')
  • 优先级 结合性操作符 左() 左-> — 右** 右 ! ~ -(单目操作符) 左=~ !~ 左* / % x 左 – .(双目操作符) 左<< >> 具名的单目操作符(-X 文件测试; rand) < <= > >= lt le gt ge == != <=> eq ne cmp 左& 左| ^ 左&& 左|| .. … 右?:(三目操作符) 右= = -= .= (以及类似的赋值操作符) 左, => 右not 左and 左or xor
  • 数值与字符串的比较操作符 比较数字字符串 相等==eq 不等!=ne 小于<lt 大于gt 小于或等于<=le 大于或等于>=ge
  • 布尔值
    • 假:0'''0'undef
  • 用户输入:<STDIN>,读取的数据会带有换行符
  • chomp:去除换行符,chomp($text = <STDIN>)
  • undef:数字使用时如同0,字符串使用时如同''
  • defined:判断是否定义 if ( defined $madonna ) {...}

第三章 列表与数组

概念

  • 列表:指的是标量的有序集合
  • 数组:存储列表的变量。数组的名字空间和标量的名字空间是完全分开的: my @test = (whq, whq2); print test; # test is undef ("first", "second") # 列表)
  • 数组索引: # 数组会按需自动扩大,中间的增补元素值都为undef rocks[0] = 0;rocks[10] = 10; # rocks[1 ~ 9] 都是undef # 负数索引 @rocks = (1..10); # 这里使用了范围操作符".." #rocks获取元素个数rocks[9]; # 10
  • 字符串中的数组内插:自动添加分隔符,此分隔符是由特殊变量$"的值指定的,默认为空格
  • 变量上下文和列表上下文 @people = qw( fred barney betty ); @sorted = sort @people; # 列表上下文,@people -> (barney, betty, fred) $number = 42 @people; # 标量上下文,@people -> 元素个数 $backwards = reverse qw/ yabba dabba doo /; # 会得到 oodabbadabbay ($dino) = something; # 列表上下文,括号即是列表 @barney = 'hello' . ' ' . 'world'; # 得到的就是一个字符串列表:("hello world") print "I have ", scalar @rocks, " rocks!n"; # scalar -> 强制引入标量上下文,@rocks会被替换成元素个数

pop、push

代码语言:javascript复制
@rocks = qw( 1 2 3 );
$elem = pop @rocks; # @rocks: 1 2, $elem: 3
push @rocks $elem; # @rocks: 1 2 3

shift、unshift

代码语言:javascript复制
@rocks = qw( 1 2 3 );
$elem = shift @rocks; # $elem: 1, @rocks: 2 3
unshift @rocks $elem; # @rocks: 1 2 3

splice

代码语言:javascript复制
# format: @delete splice @dst, 位置, 删除个数, 插入元素

# 在原来的数组中删掉fred及其后元素
# @removed 编程 qw( fred barney betty )
# 而原先的@array则编程qw( pebbles dino )
@array = qw( pebbles dino fred barney betty);
@removed = splice @array, 2;

# 删除dino和fred这两个元素
# @removed 编程 qw( dino fred )
# 而 @array 则编程 qw( prebbles barney betty )
@array = qw( pebbles dino fred barney betty );
@removed = splice @array, 1, 2;

# 删除 dino 和 fred 并插入 wilma
# @removed 变成 qw( dino fred )
# @array 变成 qw( prebblees wilma barney betty )
@array = qw( pebbles dino fred barney betty );
@removed = splice @array, 1, 2 qw( wilma );

foreach

代码语言:javascript复制
# format: foreach 控制变量 (迭代器)

foreach $line (@text)
{
    ...
}
  1. 控制变量并不是列表元素的复制品,而是列表元素的本身,修改其值也就是修改元素的值。
  2. 当循环结束后控制变量仍是循环执行之前的值。
  3. 控制变量的默认值是_,即:如果没有指定控制变量则默认使用_

reverse

  • 读取列表的值并返回次序相反的列表

sort

  • 读取列表的值,并按照排序规则进行排序(默认是按照代码点排序)
  • 数字会被当成字符串来排序

each

  • 提取hash的key-value

第四章 子程序

格式

代码语言:javascript复制
sub func_name {...}

调用子程序

  1. 使用&符号来调用:&func_name
  2. 当调用者在被调用之后,可以直接使用函数名,可不使用&符号来调用: sub func_name { return 0; } func_name
  3. 使用子程序调用的语法格式来调用,可不适用&符号来调用:func_name( @args )

注意:建议只有在调用内置的时候省略&符号,其余的都加上&符号来区分调用的是内置还是自定义子程序。

返回值

  1. 最后一次运算结果
  2. 单写一个return不给任何参数时:
    • 标量上下文:return undef;
    • 列表上下文:return ();

私有变量/词法变量

  • 临时: my $first; # 初始值: undef my @array; # 初始值: () my ( $first, @array );
  • 持久(等效C中的静态变量)
    • 限制:数组和hash使用state时,不能初始化。

    use feature state; state $first;

  • 参数:@_
  • 注意:Perl允许省略语句块中的最后一个分号,因为分号的作用仅仅是分隔语句,而不是必须的语句结束标记。
  • 建议比屏幕长的程序都加上use strict;

第五章 输入与输出

行输入操作符

  1. 唯独while/foreach循环的条件表达式中只有行输入操作符的前提下,这个简写才起作用: while (<STDIN>) {...}
  2. 在列表上下文中,会返回一个列表: @line = <STDIN>;
  3. whileforeach的区别:在while循环里,Perl会读取一行输入,把他存入某个变量并执行循环的主体,接下来它会回头去寻找其他的输入行。但是在foreach循环里,行输入操作符会在列表上下文中执行(因为foreach需要逐项处理列表内容,因此会一次性读取所有输入)

钻石操作符

  1. 在不指定文件句柄的时候,默认检查@ARGV: while (<>) {...}
    1. @ARGV:参数列表
    2. $ARGV:当前正在处理的文件
    3. 连字符-:表示要从标准输入读取数据,在没有指定参数的时候,默认为连字符。

文件句柄

  • 存在形式:虽然文件句柄可以存入标量中,但是很多时候我们写的都是应急的短小脚本,用裸字更快捷。
    • 裸字: open LOG, '>>', 'my.log'
    • 标量: open $log, '>>', 'my.log'
  • 建议:使用全大写来命名文件句柄
  • 保留:STDIN, STDOUT, STDERR, DATA, ARGV, ARGVOUT
  • 编码:
    1. open CONFIG, '<:encoding(UTF-8)', 'dino';
    2. 查看perl能理解和处理的字符编码清单:% perl -Mencode -le "print for Encode->encodings(':all')";
  • 风格转换:
    • DOS与Unix的转换:open BEDROCK, '>:crlf', $file_name;
  • 以二进制方式读写文件句柄 binmode STDOUT; binmode STDERR; binmode STDOUT, ':encoding(UTF-8)';
  • 问题句柄:文件结尾在标量上下文中是:undef
  • 关闭句柄:close
  • die处理致命错误: open LOG, '>>', 'logfile' or die "Cannot create logfile: $!";
    • $!:可读的系统错误信息
    • 如果不像显示行号和文件名,请在错误信息结尾处加上换行符: die "Not enough argumentsn";
    • 系统调用时自动检测:use autodie;
  • warn:与die用法一致,但只发出警告信息,不会终止程序的运行。
  • select:改变默认的文件输出句柄
    • 示例:
      • 用LOG替代STDOUTselect LOG;
  • 无缓冲:$| = 1;
  • print: 直接使用裸字:print LOG "limestonen"; 无法得知
  • 注意:重新打开STDINSTDOUTSTDERR时,Perl会恢复其默认的文件句柄。但其那题是,$^F没有被修改的情况下。

其他综述

  1. 命令选项多余一两个:参阅“Getopt::Long”和"Getopt::Std"
  2. 除非会改变表达式的意义,否则Perl里的括号可以省略
  3. 加入print的调用看起来像函数调用,它就是一个函数调用:适用于所有函数 print (2 3)*4; # 错误的,print (2 3)已经像一个函数调用,所以不会按照预期执行:print 5*4;
  4. printf:格式化输出
  5. say:自动加"n",通过use feature say;打开此函数。

第六章 hash

  • 概念:用唯一的字符串来索引。结构为key-value
  • 访问hash元素:$hash{key}
  • 访问整个hash:%hash
  • 列表上下文:@any_array = %some_hash;
  • 赋值:my %new_hash = %old_hash
    • 上述代码会把%old_hash展开为key-value列表,然后通过列表赋值重新构造每个key-value,最终形成新的hash%new_hash
  • 胖箭头/胖逗号(=>):胖箭头与逗号等效,所有右称为胖逗号 my %last_name = ( # hash也可以是词法变量 'fred' => 'flintstone', 'dino' => undef, 'barney'=> 'rubble', 'betty' => 'rubble', ); # 使用胖箭头的时候可以省略引号,左边的部分会自动被引起 my %last_name = ( fred => 'flintstone', dino => undef, barney => 'rubble', betty => 'rubble', );
    • 省略引号条件:如果key只是由字母,数字和下划线组成的,并且不是以数字开头那就可以省略。这类不许引号的字符序列,我们称之为裸字,因为它们是孤立存在的。
  • keys:
    • 列表上下文:返回key的列表
    • 标量上下文:返回key的个数
  • values
    • 列表上下文:返回value的列表
    • 标量上下文:返回value的个数
  • each:返回(key, value)
    • 每个hash都有自己的迭代器,因此处理不同hash的each调用可以嵌套。
    • 使用keys或values函数可以重置hash的迭代器。另外使用新列表重置整个hash时也可以重置迭代器,或者each调用遍历了整个hash的时候也能重置迭代器。然而在迭代hash过程中增加新的key-value就不太好,因为这不会重置迭代器,反而会迷惑开发人员,程序维护人员,另外还会愚弄each。
  • exists if (exists $books{"dino"}) {...}
  • person = "betty"; delete
  • 内插:不支持内插整个hash

第七章 漫游正则表达式王国

Unicode属性

  • 每个字符除了字节组合外,还附带着属性信息。(可以理解为字符特征吗?)
  • 具体查看文档:perluniprops
  • 匹配某项属性:
    • p{PROPERTY}:匹配PROPERTY属性
    • P{PROPERTY}:匹配非PROPERTY属性

量词

  • {M,N}:匹配至少M次,最多N次。
  • {M,}:匹配至少M次
  • {M}:匹配M次
  • *:等同于{0,N},此处N意味着无上限
  • :等同于{1,N},此处N意味着无上限
  • ?:等同于{0,1}

分组

  • ():捕获组,默认由序号表明。对应的序号可通过依次点算左括号(包括嵌套括号)的序号。
  • N:反向引用,N为正整数
  • g{N}:反向引用
    • N可以是负数,意味着相对于自己的位置,即往前第几个括号。
    • N可以是名字
  • $N:使用捕获组匹配的内容,N为正整数。

多选结构

  • |
代码语言:javascript复制
/fred|barney|betty/ # 可以匹配任何含有fred或者barney或者betty的字符串。

字符集

  • 匹配但字符
    • [abc]:匹配字符,且该字符是'a'或'b'或'c'
    • [a-z]:匹配字符,且该字符落在'a'到'z'之间
    • [^ab]:匹配字符,且该字符即不是'a'也不是'b'
    • [-ab]:匹配字符,且该字符是'-'或'a'或'b'
  • 可以使用简写
    • [00-177]:匹配任意一个7位的ASCII字符(0 ~ 127)
    • [w]:ASCII的话即等效为:[-a-zA-Z0-9]
  • 简写
    • w
    • d
    • s:匹配任意空白。perl15.6之前,s只能匹配[ftnr],可以通过/s/a来按老的ASCII字符语义解释
    • h:水平空白
    • v:垂直空白
    • p{Space}:匹配任意空白,等效于[hv],等效于s
    • R:匹配断行
  • 反义简写(大写)
    • W
    • D
    • S
    • P{...}
  • 注意:引入Unicode之后,所有的简写已经不再局限于ASCII了。可参阅:《know your character classes under different semantics》

其他综述

  • pattern: 模式,用来表示匹配(或不匹配)某个字符串的特征模板
  • 想认真学习正则表达式请参考:《Mastering Regular Expressions》-Jeffrey Fried(O'Reilly)
  • .
    • 匹配任意字符的通配符,除了n外。
    • 如果使用了Single模式,即s则可以匹配n

第八章 用正则表达式进行匹配

匹配操作符:m

m即Match,后面跟着即为分隔符

代码语言:javascript复制
m/pattern/modifier
m#pattern#modifier
m!pattern!modifier
m{pattern}modifier
m<pattern>modifier

如果使用/作为分隔线,那么m可以省略。

列表上下文:返回所有捕获变量的列表,如果匹配失败则返回空列表

通过g全局匹配来返回多个捕获内容

代码语言:javascript复制
my $text = "Fred dropped a 5 ton granite block on Mr.Slate";
my @words = ($text =~ /([a-z] )/ig);
print "Result: @wordsn";

通过g全局匹配来讲捕获的字符串变成hash(列表转hash)

代码语言:javascript复制
my $data = "Barney Rubble Fred Flintstone Wilma Flintstone";
my %last_name = ($data =~ /(w )s (w )/g);

模式匹配修饰符

  • i:忽略大小写
  • s:单行模式,可以匹配换行符
  • m:多行模式,^$变为匹配行开头和行结尾
  • x:忽略空白符和注释,即要匹配空白符和#需要转义
  • a:ascii模式
  • l:类似于a,只是此时取决于本地化设定
  • u:Unicode模式
  • p:自动捕获变量的名字从&,'变更为{^PREMATCH},{^MATCH},{^POSTMATCH}

锚位

  • A:匹配字符串的绝对开头
  • z:匹配字符串你的绝对末尾
  • Z:匹配行尾,即n前
  • ^:匹配字符串的绝对开头,等效于A,当使用m时,匹配行开头
  • $:匹配字符串的绝对末尾,等效于z。当使用m时,匹配行末尾
  • b:单词边界,即一组连续的w字符开头或结尾
  • G:上次匹配结束的位置

绑定操作符:=~

  • 默认情况下模式匹配的操作对象是_,绑定操作符告诉perl,拿右边的模式来匹配左边的字符串,而不是_ my

捕获

  • 捕获组存储位置:%
  • 非捕获:(?:...)
  • 命名捕获:(?<LABEL>...)
  • 反向引用:如果有多个同名补货组时,则总是指最左边的那组
    • g{LABEL}
    • k<LABEL>
  • 匹配区段之前的内容:$`
  • 匹配区段的内容:$&
  • 匹配区段之后的内容:$'

优先级

  1. 圆括号(分组或捕获):(...)(?:...)(?<LABEL>...)
  2. 量词:* ?{n,m}
  3. 锚位:abc^$AbzZ
  4. 多选结构:|
  5. 原子:a, [...]d1g{LABEL}

其他综述

  • pattern中允许内插变量
  • 保护或组的存续期:捕获变量通常能存活到下次成功匹配为止

第九章 用正则表达式处理文本

s/pattern/replace/modifier

  • 作用目标必须得是个左值 filename =~ s#^(.*)/#1.bak#;
  • 返回值:成功真,失败假
  • 分隔符可以不同
    • s{fred}{barney};
    • s[fred](barney);
    • s<fred>#barney#;
  • modifier
    • g:全局替换
    • r:使返回值编程替换后的结果,而保留变量中的原字符串
  • _ = "I saw fred with barney"; s/(fred|barney)/uL

非贪婪模式(?)

  • 默认情况下,所有量词都是贪婪模式(尽可能匹配多的字符)可通过在量词后面增加?来启用非贪婪模式(匹配尽可能少的字符)

分离字符串:split

  • 查阅文档

将列表拼接为字符串:join

  • 查阅文档

其他综述

读取UTF-8文档:use open OUT => ':encoding(UTF-8)';

命令行直接运行:查看perlrun文档

代码语言:javascript复制
% perl -p -i.bak -w -e 's/Randall/Randal/g' fred*.dat
  • -P:可以让Perl自动生成一端小程序,类似: while (<>) { print; }
  • -n:抹掉-P中自动执行的print
  • -i.bak:把$^I设置为".bak",如果你不想做备份的话,请直接写出-i
  • -e:后跟可供执行的程序

第十章 其他控制结构

  • 任何能激活或停用某段程序代码的东西都算是控制结构

if

代码语言:javascript复制
$n = 1 if ! defined $n # 此写法两边仅能是单个表达式

unless

  • if的反义
代码语言:javascript复制
$n = 1 unless $n; # 此写法两边仅能是单个表达式

while

until

  • 直到满足条件才推出循环体
代码语言:javascript复制
until {$j > $i)}
{
    $j *= 2;
}

裸块控制结构

  • 受循环控制符控制
  • 可以限定临时词法标量的作用域

自增域自减: —

for

foreach域for的关系

  • 如果连有两个分号,它就是for循环,如果没有分号,说明它是一个foreach循环
代码语言:javascript复制
# is a foreach
for (1..10)
{
    print "I can cut to $_!n";
}

循环控制

  • last LABEL:就像C语言中的break,作用于for, foreach, while, until及裸块
  • next LABEL:就像C语言中的continue,作用于for, foreach, while, until及裸块
  • redo LABEL:将控制返回到当前循环体的顶端,而不经过任何测试条件,也不会进入下一次循环
  • continue:在when中使用,继续检查向下执行
  • 带标签的块:
    1. 当你需要从内层对外层循环块进行控制时,请使用标签(LABEL),标签由w组成,但不能以数字开头。
    2. Larry建议用全大写字母命名标签。

    LINE:while(<>) { foreach (split) { last LINE if /__END__/; # 如果发现有'__END__'的标记,则跳出至标签为LINE的循环 } }

条件操作符 "?:"

逻辑运算发 "and && or ||"

短路操作符

  • 逻辑运算符同C一样有短路效应,但求值结果不是简单的布尔值,而是最后运算那部分表达式的值 my last_name = last_name{
  • 定义或操作符://
    • 只要发现左侧已定义时,就进行短路操作,无论该值是属于逻辑真还是逻辑假都会。

十一章 Perl模块

模块来源

  • 随Perl发行版一同打包的,所以安装了Perl就可以用这些模块
  • 从CPAN下载,需要自己安装
  • 使用cpan工具
  • 查看模块文档
    • % perldoc CGI :查看CGI模块文档
    • % cpan -a:查看已安装的模块

安装模块

  • 参考README和INSTALL文件
    • 使用Perl自带模块ExtUtils::MakeMaker
      1. % perl Makefile.PL
      2. % make install
        • 如果没有权限安装到系统目录,在Makefile.PL后面加上INSTALL_BASE参数:% perl Makefile.PL INSTALL_BASE=/Users/fred/lib
    • 使用另一个编译安装模块Module::Build
      1. % perl Build.PL
      2. % ./Build install
        • 如果没有权限安装到系统目录:% perl Build.PL --install_base=/Users/fred/lib
    • 运行CPAN.pm的shell:% perl -MCPAN -e shell
    • 直接使用cpan安装(推荐,简单方便)
      • % cpan Module::CoreList
    • 使用PPM(Perl Package Manager)来安装:参见http://aspn.activestate.com/ASPN/docs/ActivePerl/faq/ActivePerl-faq2.html
    • 使用轻量级安装工具:cpanm
  • 安装到工作目录
    1. 设置环境变量:% perl -Mlocal::lib export PERL_LOCAL_LIB_ROOT='/Users/fred/perl5'; export PERL_MB_OPT='--install_base /Users/fred/perl5'; export PERL_MM_OPT='INSTALL_BASE=/Users/fred/perl5'; export PERL5LIB='/path/to/perl5lib'; export PATH='/Users/fred/perl5/bin:$PATH";
    2. 加载环境变量:% cpan -I Set::Crossproduct
    3. 设置cpan配置,让后续下载安装模块时自动放置到工作目录下: % cpan cpan> o conf makeup_arg INSTALL_BASE=/Users/fred/perl5 cpan> o conf build_arg '--install_base /Users/fred/perl5' cpan> o conf commit
    4. 加载模块
      • 如果使用local::lib的话,则在Perl程序内部加入代码use local::lib;
      • 如果安装在其他地方:use lib qw( /Users/fred/perl5 );

使用模块

  • 加载模块File::Basename中的所有符号:use File::Basename;
  • 加载模块File::Basename中的符号'basename':use File::Basename qw/ basename /;
  • 不直接加载符号,但可以通过制定namespace访问 use File::Basename qw/ /; my name = '/usr/local/bin/perl';me = File::Basename::dirname name;

处理文件名 File::Basename

代码语言:javascript复制
use File::Basename;

print 'please enter a filename: ';
chomp(my $old_name = <STDIN>);

my $dirname = dirname $old_name;
my $basename = basename $old_name;

$basename =~ s/^/not/; # 增加前缀
my $new_name = "$dirname/$basename";

rename $old_name, $new_name
    or warn "Can't rename '$old_name' to '$new_name': $!";

print "$old_name, $new_namen";

路径名拼接 File:Spec

代码语言:javascript复制
use File::Basename;
use File::Spec;

print "Please enter a filename: ";
chomp(my $old_name = <STDIN>);

my $dirname = dirname $old_name;
my $basename = basename $old_name;

print "$old_name, $base_namen";

my $new_name = File::Spec->cattle($dirname, $basename); # 将依据系统去拼接路径,比如WIN7用'',Linux用'/'

rename $old_name, $new_name
    or warn " Can't rename '$old_name' to '$new_name': $!";

print "$old_name, $new_namen";

更友好的处理路径 PATH::Class

代码语言:javascript复制
my $dir = dir( qw(Users fred lib) ); # Users/fred/lib/perl5
my $subdir = $dir->subdir( 'perl5' );
my $parent = $dir->parent; # Users/fred
my $windir = $dir->as_foreign( 'Win32' ); # Usersfredlib

CGI

代码语言:javascript复制
use  CGI qw/ :all /; # 加载分组all,模块可以有不同的分组,比如::cgi,:html5

print header(),
    start_html('This is the page title');
    h1('Input parameters');

my $list_items;

foreach my $param ( param() )
{
    $list_items .= li( "$param: " . param($param) );
}

print ul( $list_items );

print end_html();

数据库接口 DBI

  • 参考书籍:《Programing the Perl DBI》-Alligator Descartes&Time Bunce(O'Reilly)
  • 参考站点:http://dbi.perl.org/

处理日期和时间 DateTime

Time::Piece

代码语言:javascript复制
use time::Piece;

my $t = localtime;
print 'The month is ' . $t->month . 'n'; # 结果:The month is Apr

第十二章 文件测试

测试操作符

  • 参考文档:% perldoc -f X
  • 建议去了解对应系统的具体内容,比如Linux/Unix下的文件,可阅读《高级环境编程》等。
  • _。 -t:对文件名无效,所以它的默认值是STDIN foreach (@lots_of_filenames) { print "
  • 虚拟文件句柄_:用上次查询过的文件信息来做当前测试 if (-r $file and -w _) {...}
  • 栈式写法:if (-w -r $file) {...},先测试-r,后测试-w
  • -T-B:测试某个文件是文本文件还是二进制文件。 但是对文件系统有一点经验的人都知道,(至少在Unix类似的操作系统下)没有任何地方会告诉你它是二进制文件还是文本文件,那么Perl是如何办到的呢?答案是Perl会作弊:
    1. 先打开文件,检查开头的几千个字节,然后作出一个合理的猜测。
    2. 如果它看到了很多空字节、不寻常的控制字符,而且还设定了高位(即第8位是1)的字节,那么它看起来就是二进制文件
    3. 如果文件里没有许多奇怪的东西,而且它看起来像文本文件,那就猜测为文本文件

    因此,它可能会有猜错的时候,所以这种猜测并不完美,不过如果你只想把编译过的文件和源文件分开,或是将HTML文件和PNG文件分开,那么这两种测试操作符还算够用。 你可能会认为-T-B出现的结果必定相反,因为文件若不是文本文件,就该是二进制文件。但是,有两种特殊情况会让测试结果相同:

    1. 如果文件不存在,两则都会返回。因为它即不是文本文件也不是二进制文件。
    2. 在空文件的情况下,两者都会返回,因为它即是空的文本文件也是空的二进制文件。

stat和lstat函数

localtime和gmtime

位运算符

  • 按位与:10 & 12
  • 按位或:10 | 12
  • 按位异或:10 ^ 12
  • 按位左移:6 << 12
  • 按位右移:25 >> 2
  • 按位取反:~10
  • 注意:加入按位运算操作符的任何一个操作数是字符串,则perl会把它当成位字符串来处理:
    • "xAA" | "x55":结果为"xFF"

十三章 目录操作符

chdir

  • 功能:改变当前的工作目录
代码语言:javascript复制
chdir 'etc' or die "connot chdir to /etc: $!";
  • 如果调用chdir时不加参数,会回到自己的用户主目录,并试着将工作目录设成主目录。
  • 可以使用第三方模块:FILE::HomeDir

文件名通配符

  • 程序内部使用通配符globmy @all_files = glob '*.pm';
    • glob操作符的效果之所以和shell完全相同,是因为在Perl5.6以前它只不过是在后台调用/bin/csh来展开文件名。因此文件统配非常耗时,而且可能在目录太大时崩溃。当然,如果是新版本则无需担心此问题。
  • dir = '/etc'; my @dir_files = <

目录句柄 opendir readdir closedir

代码语言:javascript复制
my $dir_to_process = '/etc';

opendir my $dh, $dir_to_process
    or die "Can't open $dir_to_process: $!";

foreach $file (readdir $dh)
{
    print "one file in $dir_to_proces is $filen";
}

close $dh;

递归访问目录 File::Find

  • 其他模块:File::Find:RuleFile::Finder
  • % find2perl . -name '*.pm' #!/usr/bin/perl -w eval 'exec /usr/bin/perl -S 0 {1 "

删除文件 unlink

重命名/移动文件 rename

  • 重命名:rename 'old.txt' => 'new.txt';
  • 移动:rename 'over_there/some/place/some_file' => 'some_file';
  • 批量改名 foreach my file (glob "*.old") { my newfile = file =~ s/.oldnewfile) { warn "can't rename newfile existsn"; } elsif (rename file to newfile failed:

链接 link symlink readlink

  • 硬链接:link
  • 软链接:symlink
  • 读取软链接的真实位置:readlink

创建/删除目录 mkdir rmdir File::Temp File::Path

修改权限 chmod File::chmod

修改隶属关系 chown

修改时间戳 utime

第十四章 查找子字符串

查找字符串 index

反向查找字符串 rindex

操作字符串 substr

格式化字符串 sprintf

  • hex
  • oct

排序 sort

代码语言:javascript复制
my @result = sort &bynumber, @array;

sub by_number {
    if ($a < $b) { -1 } elsif ($a > $b) { 1 } else { 0 };
}
  • 比较: 数字<=>:a cmp b;
  • 注意:出于性能考虑,a和a和a和b并非数据项拷贝,实际上他们是原始列表元素的别名,所以切勿中途改变他们。

第十五章 智能匹配与given-when结构

  • 智能匹配符:~~,可查看文档,"perlop"和"perlsyn"
    • 用于判断事物是否相同(或则差不多相同),所以在需要比较大小时,就不能用智能匹配了,此时还是用传统的比较符好。
  • given结构:对应C语言的switch use 5.010001; # 至少是5.10.1版本 use experimental qw( smartmatch switch ); # 使用实验性功能,智能匹配和given-when结构 # 将参数放入_,同时每个when条件都尝试用表达式匹配对_做测试 given(
  • 在foreach中使用when foreach ( @names ) # 不要使用具名变量,需要放入到$_中 { when ( 'Fred' ) { say 'Name is Fred'; } when ( /AFred/ ) { say 'Name starts with Fred'; continue } when ( /fred/i ) { say 'Name has fred in it'; } default { say "I don't see a Freds"; } }
  • 笨拙匹配:正常的判断真假,而不是用智能匹配符去测试$_
    • 在when中调用子程序/内置函数
    • 否定表达式,包括否定的正则表达式

第十六章 进程管理

  • 建议:在此不做详细解读,请阅读《UNIX高级环境编程》

system

代码语言:javascript复制
system 'date';

# 通过使用参数来避免使用shell

my $tarfile = 'something*wicked.tar';
my @dirs = qw( fred|flintstone <barney&rubble> betty );
system 'tar', 'cvf', $tarfile, $tarfile, @dirs; # 也就是说参数最后回被引号括起来,并不会被shell解析,具体请查看perlfunc

Unix中,退出值0表示正常,非0表示有问题

环境变量:%ENV

exec

代码语言:javascript复制
exec 'date';
die "date couldn't run: $!"

反引号

  • 注意:如果不需要返回值,请用system替代反引号,提高效率
  • 上下文
    • 标量上下文:返回一个很长的字符串,包括换行符
    • 列表上下文:返回一个按行拆分的列表
代码语言:javascript复制
`date`; # system 'date'

# 好处:
#   a. 避免对反引号转义

qx

  • qx( perldoc -t -f _ ):等效于`perl perldoc -t -f _`
  • 好处 避免对反引号转义 如果选用'(单引号)作为分隔符的话,可以禁止变量内插:qx'perldoc -t -f _',此时_不会被perl解释

IPC::System::Simple

  • 执行外部命令时,不会通过shell调用,所以不会碰到shell导致意外的状况
  • 通过capture或capturex就可以捕获外部命令的输出了
代码语言:javascript复制
use IPC::System::Simple qw( system systems captures )

my $tarfile = 'something*wicked.tar';
my @dirs = qw( fred|flintstone <barney&rubble> betty );
system 'tar', 'cvf', $tarfile, @dirs;
systemx 'tar', 'cvf', $tarfile, @dirs;
my @output = captures 'tar', 'cvf', $tarfile, @dirs;

通过文件句柄执行外部进程

  • 输出重定向:open DATE, 'date|' or die "can't pipe from date: $!";
  • 输入重定向:open MAIL, '|mail merlyn' or die "can't pipe to mail: $!"
  • -|:读取的文件句柄,-相当于外部命令的占位符
  • |-:写入的文件句柄,-相当于外部命令的占位符
代码语言:javascript复制
open my $date_fh, '-|', 'date' or die "can't pipe from date: $!"
open my $mail_fh, '|-', 'mail merlyn' or die "can't pipe to mail: $!"

my $now = <$date_fh>; # 开始执行并读取响应结果

print $mail_fh "the time is now $now"; # 写入邮件,假设$now以换行符结尾
  • 注意:如果外部进程在连接到某个以读取模式打开的文件句柄后自行退出运行,那么这个文件句柄就会返回文件结尾标识符,好像已经读完了正常文件一样。当你关闭用来写入数据到某个进程的文件句柄时,该进程会读到文件结尾标识符。所以,要结束邮件的发送,只需要关闭这个文件句柄即可。
  • mail_fh; die "mail: non-zero exit of
  • $?也会存储system和反引号圈引的命令的返回值

fork exec waitpid

代码语言:javascript复制
defined( my $pid = fork ) or die "Cannot fork: $!";

unless ( $pid )
{
    # subprocess
    exec 'date';
    die "can't exec date: $!";
}

# parent process

waitpid( $pid, 0 );

信号、kill

  • 发送信号:kill kill 2, 4201 or die "can't signal 4201 with SIGINT: $!"; kill 'INT', 4201 or die "can't signal 4201 with SIGINT: $!"; kill INT => 4201 or die "can't signal 4201 with SIGINT: $!"; unless (kill 0, $pid) { warn "$pid has gone away!"; }
  • signal 0:测试能否向指定进程发信号,但并不是真的发送
  • 信号处理函数:%SIG。key是非前缀信号名,如INT。value是信号处理函数名。 sub clean_up; sub my_int_handler; my temp_directory = "/tmp/myprog."; mkdir
  • 注意:Perl会立即处理SIGKILL、SIGBUS以及SIGSEGV这些信号,所以对进程运行而言,这些信号可能会造成不安全。

第十七章 高级Perl技巧

切片

  • 切片后的结果是:列表
  • 切片和列表的区别:切片可以内插到字符串中,但列表不行
  • 列表切片 my (card_num, count) = (split /:/)[1, 5]; my (first, last) == (sort names)[0, -1]; # 切片可以指定负数,用来表示倒数的元素
  • 数组切片 my @numbers = @names[9, 0, 2, 1, 0]; @items[2, 3] = (new_address, new_home_phone); # 修改指定元素值
  • 理解变量的前置符号及后置括号
    • 前置符号:
      • $:一个元素
      • @:一组元素
      • %:一整个hash
    • 后置括号:
      • []:访问列表(切片)
      • {}:访问hash元素
  • hash切片 my %hash_t = ( a => 1, b => 2, c => 3, ); print "hash_t{a, c}";

eval

  • eval块中出现致命错误时会立即停止运行整个块,然后退出继续运行其余的代码。
  • eval是一个表达式,所以末尾需要一个分号。
  • @变量中。 my barney = eval { barney = red / dino } // 'NAN'; # 如果捕获到错误则额返回'NAN' unless ( eval { red / dino } ) { print "I couldn't divide by dino: @" if @; } # 如果eval块中的表达式中的返回值没有什么异议,则可以通过如下方法 unless ( eval { some_sub(); 1 } ) { print "I couldn't divide by
  • eval无法捕获到的错误
    1. 源码中的语法错误
    2. perl解释器本身崩溃的错误
    3. 警告
    4. 调用exit退出
  • 由于$@是一个特殊变量,而你所写的eval也许会被另一个高层的eval包裹,所以就要确保出现的错误不干扰高层出现的错误 { local $@; # 不干扰高层错误 eval { ...; } ...; }

Try::Tiny

代码语言:javascript复制
use Try::Tiny

try
{
    # 某些可能会抛出异常的代码
}
catch
{
    # 某些处理异常的代码
}
finally
{
    # 一定会指定的代码
}
  • 为了避免干扰@,Try::Tiny把错误消息放到了默认变量_里。 my barney = Try { fred /

grep

  • 格式:@dst_list grep { selector } @src_list;
  • grep会将@src_list中的每个元素放到$_中并执行代码块selector,最后将返回真的元素以列表的形式返回,即@dst_list
  • 由于_是@src_list中元素的别名,所以不要修改_
  • 标量上下文的grep返回符合过滤条件的元素个数

map

  • 于grep区别
    1. map使用代码块中的最后一个表达式的实际计算结果,所以最终会返回一个这样的结果组成的列表。
    2. map使用的表达式(selector)是在一个列表上下文环境中,意味着可以一次返回多个元素的结果

    my @data = (4.75, 1.5, 2, 1234, 6.9456, 12345678.9, 29.95); print "The money number are:n", map { sprintf("%sn", $_) } @data;

List::Util

  • 高效处理列表的工具
  • 前言
  • 问题
  • 建议和总结
  • 书籍
  • 站点
  • 特殊变量
  • 第一章 简介
  • 第二章 标量数据
  • 第三章 列表与数组
    • 概念
    • pop、push
    • shift、unshift
    • splice
    • foreach
    • reverse
    • sort
    • each
  • 第四章 子程序
    • 格式
    • 调用子程序
    • 返回值
    • 私有变量/词法变量
  • 第五章 输入与输出
    • 行输入操作符
    • 钻石操作符
    • 文件句柄
    • 其他综述
  • 第六章 hash
  • 第七章 漫游正则表达式王国
    • Unicode属性
    • 量词
    • 分组
    • 多选结构
    • 字符集
    • 其他综述
  • 第八章 用正则表达式进行匹配
    • 匹配操作符:m
    • 模式匹配修饰符
    • 锚位
    • 绑定操作符:=~
    • 捕获
    • 优先级
    • 其他综述
  • 第九章 用正则表达式处理文本
    • s/pattern/replace/modifier
    • 非贪婪模式(?)
    • 分离字符串:split
    • 将列表拼接为字符串:join
    • 其他综述
  • 第十章 其他控制结构
    • if
    • unless
    • while
    • until
    • 裸块控制结构
    • 自增域自减: —
    • for
    • foreach域for的关系
    • 循环控制
    • 条件操作符 "?:"
    • 逻辑运算发 "and && or ||"
    • 短路操作符
  • 十一章 Perl模块
    • 模块来源
    • 安装模块
    • 使用模块
    • 处理文件名 File::Basename
    • 路径名拼接 File:Spec
    • 更友好的处理路径 PATH::Class
    • CGI
    • 数据库接口 DBI
    • 处理日期和时间 DateTime
    • Time::Piece
  • 第十二章 文件测试
    • 测试操作符
    • stat和lstat函数
    • localtime和gmtime
    • 位运算符
  • 十三章 目录操作符
    • chdir
    • 文件名通配符
    • 目录句柄 opendir readdir closedir
    • 递归访问目录 File::Find
    • 删除文件 unlink
    • 重命名/移动文件 rename
    • 链接 link symlink readlink
    • 创建/删除目录 mkdir rmdir File::Temp File::Path
    • 修改权限 chmod File::chmod
    • 修改隶属关系 chown
    • 修改时间戳 utime
  • 第十四章 查找子字符串
    • 查找字符串 index
    • 反向查找字符串 rindex
    • 操作字符串 substr
    • 格式化字符串 sprintf
    • 排序 sort
  • 第十五章 智能匹配与given-when结构
  • 第十六章 进程管理
    • system
    • Unix中,退出值0表示正常,非0表示有问题
    • 环境变量:%ENV
    • exec
    • 反引号
    • qx
    • IPC::System::Simple
    • 通过文件句柄执行外部进程
    • fork exec waitpid
    • 信号、kill
  • 第十七章 高级Perl技巧
    • 切片
    • eval
    • Try::Tiny
    • grep
    • map
    • List::Util

≡ var sidebarTOCBtn = document.getElementById('sidebar-toc-btn') sidebarTOCBtn.addEventListener('click', function(event) { event.stopPropagation() if (document.body.hasAttribute('html-show-sidebar-toc')) { document.body.removeAttribute('html-show-sidebar-toc') } else { document.body.setAttribute('html-show-sidebar-toc', true) } })

0 人点赞