Skip to content

Perl 特殊变量

输入输出特殊变量

$_ - 默认输入和模式搜索变量

perl
# 在循环中使用默认变量
foreach (1..5) {
    print;  # 打印 $_
}

# 在模式匹配中使用
$_ = "Hello World";
print if /World/;  # 如果包含 World 则打印

# 在 grep 和 map 中使用
my @evens = grep { $_ % 2 == 0 } (1..10);
my @squared = map { $_ * $_ } (1..5);

@_ - 子程序参数数组

perl
sub add {
    my ($a, $b) = @_;
    return $a + $b;
}

print add(10, 20);  # 30

$. - 当前行号

perl
while (my $line = <STDIN>) {
    print "Line $.: $line";
}

$/ - 输入记录分隔符

perl
# 读取整个文件
local $/;
my $content = <FILE>;

# 段落模式(空行分隔)
$/ = "";
my @paragraphs = <FILE>;

# 自定义分隔符
$/ = "---\n";
my @records = <FILE>;

$\ - 输出记录分隔符

perl
local $\ = "\n";  # 每次打印后自动添加换行符
print "Hello";     # 输出:Hello\n
print "World";     # 输出:World\n

$| - 自动刷新

perl
$| = 1;  # 启用自动刷新
print "Processing...";  # 立即输出
sleep(2);
print "Done\n";

$" - 列表内插分隔符

perl
$" = ", ";
my @array = (1, 2, 3);
print "@array";  # 输出:1, 2, 3

$, - 输出字段分隔符

perl
$, = " - ";
print "a", "b", "c";  # 输出:a - b - c

模式匹配特殊变量

$1, $2, $3, ... - 捕获组

perl
if ("hello world" =~ /(hello) (\w+)/) {
    print "$1\n";  # hello
    print "$2\n";  # world
}

if ("2024-01-15" =~ /(\d{4})-(\d{2})-(\d{2})/) {
    print "Year: $1, Month: $2, Day: $3\n";
}

$& - 匹配的字符串

perl
if ("hello world" =~ /world/) {
    print "Matched: $&\n";  # world
}

`$`` - 匹配前的字符串

perl
if ("hello world" =~ /world/) {
    print "Before: $`\n";  # hello 
}

$' - 匹配后的字符串

perl
if ("hello world" =~ /world/) {
    print "After: $'\n";  # 空
}

if ("hello world test" =~ /world/) {
    print "After: $'\n";  #  test
}

$+ - 最后一个捕获组

perl
if ("test@example.com" =~ /(\w+)@(\w+)\.(.+)/) {
    print "Last capture: $+\n";  # com
}

$^N - 最近完成的捕获组

perl
if ("test123" =~ /(test)(\d+)/) {
    print "Most recent: $^N\n";  # 123
}

进程特殊变量

$$ - 当前进程 ID

perl
print "PID: $$\n";

$? - 最后一个子进程的退出状态

perl
system("ls -l");

if ($? != 0) {
    print "Command failed with status: $?\n";
}

# 获取退出码和信号
my $exit_status = $? >> 8;
my $signal = $? & 127;

$0 - 程序名

perl
print "Program name: $0\n";

$^O - 操作系统名

perl
print "OS: $^O\n";  # linux, darwin, MSWin32 等

$^T - 脚本开始时间

perl
my $start_time = $^T;
print "Start time: ", scalar localtime($start_time), "\n";

# 计算运行时间
my $elapsed = time - $^T;
print "Elapsed: $elapsed seconds\n";

$^X - Perl 解释器路径

perl
print "Perl interpreter: $^X\n";

文件句柄特殊变量

ARGV - 命令行参数

perl
# 读取命令行指定的文件
while (<>) {
    print;
}

# 访问当前文件名
print "Current file: $ARGV\n";

@ARGV - 命令行参数数组

perl
foreach my $arg (@ARGV) {
    print "Argument: $arg\n";
}

STDIN, STDOUT, STDERR

perl
# 标准输入
my $input = <STDIN>;

# 标准输出
print STDOUT "Output to STDOUT\n";

# 标准错误
print STDERR "Error message\n";

格式化特殊变量

$# - 数组最后一个索引

perl
my @array = (10, 20, 30);
print "Last index: $#array\n";  # 2
print "Array size: " . ($#array + 1) . "\n";  # 3

$% - 当前页号

perl
# 在格式化输出中使用
format STDOUT_TOP =
Page @<
$%
.

$= - 每页行数

perl
$= = 50;  # 设置每页 50 行

$- - 当前行数

perl
print "Lines left on this page: $-\n";

$~ - 当前格式名

perl
$~ = "MYFORMAT";
format MYFORMAT =
@<<<<<<<<<< @<<<<<<<<< @>>>>>>>
$name, $email, $salary
.

正则表达式特殊变量

$^R - 最后成功的正则表达式代码执行结果

perl
if ("test123" =~ /(?{$count++})test/) {
    print "Code executed $^R times\n";
}

其他重要特殊变量

$! - 系统错误消息

perl
open(my $fh, '<', 'nonexistent.txt')
    or die "Error: $!";

$@ - eval 错误消息

perl
eval {
    die "An error occurred";
};

if ($@) {
    print "Error: $@\n";
}

$^E - 扩展错误消息

perl
open(my $fh, '<', 'file.txt') or die "Error: $!, $^E";

$^I - 原地编辑备份扩展名

perl
local $^I = '.bak';  # 创建备份文件

while (<>) {
    s/foo/bar/g;  # 替换 foo 为 bar
    print;        # 输出修改后的内容
}

# 运行:perl -i.bak script.pl file1.txt file2.txt

$^F - 系统文件描述符最大值

perl
print "Max file descriptors: $^F\n";

$^H - 语法哈希(内部使用)

perl
# 用于修改编译器行为

$^M - 紧急内存池

perl
# 用于内存不足时的紧急分配
$^M = ' ' x 1024 * 1024;

$^P - 调试器标志

perl
$^P = 0x01;  # 启用单步调试

$^S - 当前解释器状态

perl
eval {
    print "In eval: $^S\n";  # 1
};

print "Not in eval: $^S\n";  # 0

$^V - Perl 版本

perl
my $version = $^V;
printf "Perl version: v%d.%d.%d\n",
       $version->[0], $version->[1], $version->[2];

实践示例

示例 1:行号和文件处理

perl
#!/usr/bin/perl
use strict;
use warnings;

my $file = shift or die "Usage: $0 <filename>";

open(my $fh, '<', $file) or die "Cannot open $file: $!";

my $line_count = 0;

while (my $line = <$fh>) {
    chomp $line;
    $line_count++;
    printf "%4d: %s\n", $., $line;
}

close($fh);

print "\nTotal lines: $line_count\n";

示例 2:正则表达式提取

perl
#!/usr/bin/perl
use strict;
use warnings;

my $text = "Contact us at support@example.com or sales@example.com";

while ($text =~ /(\w+)@(\w+)\.(\w+)/g) {
    print "Email: $&\n";
    print "Username: $1\n";
    print "Domain: $2\n";
    print "TLD: $3\n";
    print "Context: $` <<MATCH>> $'\n";
    print "-" x 40 . "\n";
}

示例 3:命令行工具

perl
#!/usr/bin/perl
use strict;
use warnings;

print "Script name: $0\n";
print "Arguments:\n";

foreach my $i (0..$#ARGV) {
    print "  [$i] $ARGV[$i]\n";
}

print "\nTotal arguments: " . scalar(@ARGV) . "\n";
print "Perl version: $^V\n";
print "OS: $^O\n";
print "PID: $$\n";

# 读取命令行指定的文件
if (@ARGV) {
    print "\nProcessing files:\n";
    while (<>) {
        print "File $ARGV, Line $.: $_";
    }
}

示例 4:进度显示

perl
#!/usr/bin/perl
use strict;
use warnings;

use Time::HiRes qw(sleep);

$| = 1;  # 启用自动刷新

my @files = ('file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', 'file5.txt');
my $total = scalar(@files);

print "Processing $total files...\n";

for my $i (0..$#files) {
    my $progress = ($i + 1) / $total * 100;
    printf "\rProgress: [%-50s] %.0f%% (%d/%d)",
           "=" x ($progress / 2),
           $progress,
           $i + 1,
           $total;
    
    sleep 0.5;  # 模拟处理
}

print "\nDone!\n";

小结

本章节学习了 Perl 的特殊变量:

  1. ✅ 输入输出特殊变量
  2. ✅ 模式匹配特殊变量
  3. ✅ 进程特殊变量
  4. ✅ 文件句柄特殊变量
  5. ✅ 格式化特殊变量
  6. ✅ 其他重要特殊变量

接下来,我们将学习 Perl 正则表达式