发布于2026-06-29 阅读(0)
扫一扫,手机访问
Perl——Practical Extraction and Report Language——拥有大量命令行参数,善用它们能让你的脚本精简到极致,甚至一行命令就搞定所有事情。这篇文章就来系统梳理一下那些最常用的命令行参数。

命令行调用
[开关项描述]
-0
规定记录分隔符。
-0<数字>
(用8进制表示)指定记录分隔符($/变量),默认为换行。
-00
段落模式,即以连续换行为分隔符。
-0777
禁用分隔符,将整个文件作为一个记录。
-a
与 -n 或 -p 搭配,打开自动拆分模式。默认按空白字符拆分,结果存入@F,相当于@F = split ''。可以通过 -F 自定义分隔符。举个例子:
-c
只检查 Perl 脚本语法,不执行。每次修改脚本后第一时间用它来捉语法错误。
-d
启动 Perl 调试器。
-D
设置调试标记。例如 -D14 可以观察脚本的执行过程。使用前请确认调试器已正确安装。
-e command
直接在命令行执行 Perl 代码,无需写脚本文件。这是单行命令的基石。
-F pattern
指定拆分输入行时的模式。模式是正则表达式,可以放在斜杠、单引号或双引号中。例如 -F/:+/ 表示按一个或多个冒号拆分。如果同时使用 -a,则自动生效。
-h
打印 Perl 命令行选项列表。
-i extension
启用原位编辑模式。使用 <> 循环遍历文件时,如果需要修改原文件,-i 就派上用场了。如果提供扩展名(如 .bak),则原始文件会被备份为 原文件名.扩展名,然后修改写入原文件。如果不提供扩展名,则直接覆盖。
-I directory
与 -P 配合,告诉 C 预处理程序去哪里查找包含文件。默认路径包括 /usr/include、/usr/lib/perl 和当前目录。
-l digits
启用自动行尾处理。与 -n 或 -p 一起使用时,会自动移除输入行的换行符,并将输出行附加换行符。如果不指定数字,则把 $/ 的当前值赋给 $\。简单理解:-l 同时做了两件事——自动 chomp 输入分隔符,并在 print 时自动加换行。
在执行 Perl 脚本之前调用 use 方法。其中 -M 相当于 use Module;,-m 相当于 use Module ();(即不导入默认符号)。方括号中的短横线表示将 use 替换为 no。
-n
让 Perl 隐式循环遍历所有文件。相当于 while (<>) { 脚本; }。每一行默认保存在 $_ 中。
-p
类似 -n,但会在循环末尾自动打印 $_。相当于 while (<>) { 脚本; print; }。简单来说,-p 适合完全处理文件,-n 适合选择性输出。
-P
在 Perl 编译之前先通过 C 预处理程序处理脚本。
-s
启用自定义开关解析。脚本名之后、文件名参数之前的开关会被解析为对应的标量变量(如 -abc 会生成 $abc 并赋值为 1),并从 @ARGV 中删除。
-S
如果脚本首行不是 #!/usr/bin/perl,则让 Perl 在 PATH 环境变量中搜索脚本。
-T
强制打开“污染”检查(taint mode),常用于测试 setuid/setgid 程序,也推荐用于 CGI 脚本。
-u
编译后产生核心转储(仅 Unix 系统)。
-U
允许 Perl 执行不安全操作,例如超级用户断开目录链接。
-v
打印 Perl 版本信息。
-V
打印重要配置项和 @INC 数组的汇总。
-V:NAME
打印指定配置变量 NAME 的值。
-w
打印警告信息,包括保留字误用、文件句柄错误等。
-W
启用所有警告,即使局部代码中用 no warnings 关闭了也无效。
-x directory
忽略 #!/usr/bin/perl 行之前的任何文本。如果指定了目录名,Perl 会在执行前自动切换到该目录。
-X
关闭所有警告。
另外提一句:-p 和 -n 都隐式地把每一行保存在 $_ 中,区别仅在于 -p 会自动打印 $_。
安全网参数
有三个参数堪称“安全网”,尤其当你用 Perl 玩一些“聪明”或疯狂的想法时,它们能让错误提前现形。经验丰富的 Perl 程序员几乎离不开它们。
首先是 -c。编译但不执行,只检查语法错误。每次修改脚本后先跑一遍 perl -c program.pl,确保编译通过。在输入少量代码时就检查,比后面面对几百行代码再 debug 轻松得多。
第二个是 -W,它开启所有警告,能揪出潜在的 bug。不过 Perl 5.6.0 之后推荐在脚本内使用 use warnings;,因为更灵活。
第三个是 -T,进入 taint 模式。Perl 会怀疑所有来自外部的数据(命令行、文件、CGI 输入),这些数据被“污染”后不能直接用于 system 调用、open 等危险操作。要使用它们,必须通过正则表达式“去污染”。taint 模式本身内容很多,这里不展开,但如果你在写 CGI 等需要接收用户输入的程序,强烈推荐开启 taint 模式。
另外 -d 参数进入调试器模式,详细内容可参考 perldoc perldebug 或 Richard Foley 的 Perl Debugger Pocket Reference。
使用模块
下面几个参数让命令行上的 Perl 程序更简洁。-e 可以直接执行代码,比如一行搞定“Hello World”:
多个 -e 可以按顺序执行:
引入模块时,-M 比在 -e 中用 use 更方便:
-M 等同于 use Module;,包含默认导入。如果不想要默认导入,就用 -m,它相当于 use Module ();。例如下面的例子因为 head 函数是默认导入,使用 -m 时不会被导入,所以什么也输出:
-m 和 -M 还支持在 = 后附加参数,比如引入 :standard 标签:
要引入多个参数,可以用引号加逗号分隔:
隐式循环
-n 和 -p 为逐行处理文件提供了循环框架。
相当于:
每一行自动存入 $_。下面的例子输出行号和内容:
而 -p 会自动调用 print,所以同样的效果可以写成:
注意隐式循环中有一个 LINE: 标签,可以用 next LINE 直接跳到下一个输入记录,这在多层嵌套时非常有用:
当然也可以简化成 print unless /pattern/。如果需要在循环前后做额外处理,可以使用 BEGIN 或 END 块。下面这个例子统计文本文件中的总字数:
如果再加上 -a,自动拆分模式会把每行按空白分割成数组 @F,上面的代码可以更简洁:
通过 -F 可以自定义拆分规则。例如按非单词字符拆分:
一个经典的例子:分析 Unix 密码文件(/etc/passwd),按冒号拆分,统计每个 shell 路径被多少用户使用:
输出类似:
数据分隔符
之前提到过 $/(输入记录分隔符)和 $\(输出记录分隔符)。$/ 默认是换行符,所以一次读一行。$\ 默认为空,因此 print 时需要手动加 \n。在命令行中,-0(零)对应 $/,-l(字母 L)对应 $\。-0 后面可以跟八进制或十六进制数值,例如 -00 进入段落模式(连续换行分隔),-0777 进入 slurp 模式(一次读入整个文件)。-l 单独使用有两个效果:一是自动 chomp 输入分隔符,二是把 $/ 的值赋给 $\,这样 print 时自动加换行。个人常常使用 -l 来省去末尾的 \n:
原位编辑
配合 -i 参数,可以原地修改文件,而不需要 I/O 重定向。例如将所有 PHP 替换为 Perl(整词匹配):
如果想保留备份,就加个扩展名:
处理后的结果写入 file.txt,原始文件则被重命名为 file.txt.bak。
打开Perl的taint模式
如果程序从外部接收数据,并且这些数据会影响到程序之外的东西(比如系统调用),那么就应该用 -T 开启 taint 模式。Perl 会检查数据是否被“污染”,如果未经处理就用于危险操作,会抛出一个致命错误。去污染的唯一方法是用正则表达式匹配并提取你想要的部分,从而明确描述数据的格式。例如,期望收到一个单词字符:
Perl命令行调试
缺省的 Perl 调试器就是解释器本身,启动方式很简单:perl -d test.pl。进入交互界面后,常用命令如下(所有命令在调试提示符下输入,大小写有关):
h:显示帮助。|h:分页显示帮助。p 表达式:打印变量或表达式的值(不显示复杂结构)。x 表达式:打印变量值,对复杂数据以可读形式展示。V 包名 变量列表:显示指定包内的变量(包名默认 main)。X 变量列表:显示当前包内的变量。T:调用栈回退一级。s:单步执行,进入子函数(step into)。n:单步执行,越过子函数(step over)。c 行号/函数名:执行到指定行或函数。l:显示未执行的一屏代码。l min-max:显示指定行范围。/模式:向前查找。?模式:向后查找。b 行号 [条件]:设置断点。b 函数名 [条件]:函数断点。d 行号:删除断点。D:删除所有断点。a 行号 命令:添加附加操作(执行该行前先执行命令)。W 表达式:添加监视项。!number:重复执行之前第 number 次调试命令。!!命令:执行 shell 命令而不退出调试器。q:退出。更多细节可参考 perldoc perldebug。
更多信息
Perl 命令行参数远不止这些,本文只列出了最实用的一部分。完整列表请参考 perlrun 文档。
命令行的运用
Perl 在命令行下完全可以替代 sed、awk 等工具。有经验的程序员不应回避那些看似“丑陋”但高效的快速解决方法。
Perl单行命令示例
先看参数如何被接收:
-e 后的内容被当作脚本执行。-M 导入模块。注意单引号比双引号更安全,因为 shell 不会转义里面的变量。
上例打印当前进程 PID,单引号保护了 $$ 不被 shell 解释。
原地替换:
类似 grep 过滤:
加行号打印:
使用 -p 简化:
利用 -a 和 -F 进行字段处理:
打印从 START 到 END 之间的行:
打印指定行号范围:
原地替换并备份:
反向每一行:
替换
所有 C 程序中的 foo 替换为 bar,旧文件备份为 .bak:
将每个文件中的数字加一:
将 \r\n 替换为 \n(类似 dos2unix):
反向(类似 unix2dos):
取出文件的一部分
显示字段 0-4 和字段 6(默认空格分隔):
如果分隔符是冒号(如 /etc/passwd):
显示 START 和 END 之间的部分:
不显示中间部分:
显示前 50 行:
跳过前 10 行:
显示第 15 到 17 行:
每行取前 80 个字符:
每行丢弃前 10 个字符:
搜索
查找包含 comment 的行:
查找不含 comment 的行:
查找包含 comment 或 apple 的行:
计算
计算第 5 字段和倒数第 2 字段之和:
排序和反转
文件按行排序:
文件按段落排序:
合并多个文件后整体排序:
文件按行反转:
数值计算
十进制转十六进制:
十进制转八进制:
十六进制转十进制:
八进制转十进制:
简易计算器:
批量重命名文件
利用 File::Find 模块遍历目录并改名。例如将 帝王之死001.mp3 重命名为 01.mp3:
更复杂的例子,去掉中文引号、替换分隔符等,这里不再一一展开,核心就是 find 结合正则表达式。
在命令行下查看当前目录下的目录
使用内置 File::Find 列出所有子目录(包括深层):
使用 File::Find::Rule 更直观,只列一级目录:
对目录下的文件进行大小写修改
将大写目录名改为小写:
统计相关的tcp连接情况
查看 IP 尾数为 9、端口 80 的所有连接:
按连接数降序排列,显示前 20 个 IP:
统计连接状态:
统计文本文件行数,有多种写法,但实测 wc -l 效率最高。
其他
启动交互式 Perl 调试器:
查看 @INC 路径:
perl 生成随机密码
核心是利用 rand 函数。生成 25 到 75 之间的随机数:
从数组中随机取一个元素:
生成 8 位包含特殊字符的随机密码:
更灵活的方式:
一行命令生成 42 位密码:
也可以调用 String::Random 模块:
相关问题:Perl one-liner 中处理单引号
在命令行中,单引号嵌套容易出问题。假设你想输出带单引号的字符串:
如果直接试图包裹单引号,可能会失败。解决办法:1)使用双引号包裹外层,内部用转义;2)使用 ASCII 码 \047。例如:
或者:
这些技巧在实际的单行命令中很实用,值得收藏。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8