Perl 标量
Perl - 标量
Section titled “Perl - 标量”标量(Scalar)是 Perl 的基本数据类型,用于表示单个值。这个值可以是一个数字(整数或浮点数)、一个字符串,或者一个引用(Reference,是一种指向其他数据结构的标量,例如数组、哈希或子例程)。标量变量以美元符号($)作为前缀。
这是一个展示标量变量的基本示例:
#!/usr/bin/perluse strict;use warnings;
my $age = 30; # 一个整数my $name = "Alice Wonderland"; # 一个字符串my $price = 19.99; # 一个浮点数my $undefined_var; # 最初是 'undef'
print "Name: $name\n";print "Age: $age\n";print "Price: $price\n";
if (defined $undefined_var) { print "Undefined Var: $undefined_var\n";} else { print "Undefined Var is undef\n";}这将产生以下结果:
Name: Alice WonderlandAge: 30Price: 19.99Undefined Var is undef数值型标量可以是整数或浮点数。Perl 会根据需要自动在它们之间进行转换。数字也可以用八进制(以 0 为前缀)或十六进制(以 0x 为前缀)指定。数字内部可以使用下划线来提高可读性(例如,1_000_000)。
#!/usr/bin/perluse strict;use warnings;
my $integer_val = 2023;my $negative_val = -50;my $float_val = 3.14159;my $scientific_notation = 6.022e23; # 阿伏伽德罗常数
my $octal_val = 0377; # 十进制的 255 (3*64 + 7*8 + 7*1)my $hex_val = 0xFF; # 十进制的 255 (15*16 + 15*1)my $large_number = 1_234_567.89;
print "Integer: $integer_val\n";print "Negative: $negative_val\n";print "Float: $float_val\n";print "Scientific: $scientific_notation\n";print "Octal (0377) in decimal: $octal_val\n";print "Hex (0xFF) in decimal: $hex_val\n";print "Large Number: $large_number\n";输出:
Integer: 2023Negative: -50Float: 3.14159Scientific: 6.022e+23Octal (0377) in decimal: 255Hex (0xFF) in decimal: 255Large Number: 1234567.89字符串型标量
Section titled “字符串型标量”字符串型标量是字符序列。它们可以使用单引号('...')或双引号("...")定义。
- 单引号字符串: 几乎不做内插(interpolation)。只有
\'(用于嵌入单引号)和\\(用于嵌入反斜杠)是特殊的。 - 双引号字符串: 执行变量内插(例如,
$variable会被替换为其值)和转义序列处理(例如,\n表示换行,\t表示制表符)。
#!/usr/bin/perluse strict;use warnings;
my $fruit = "apple";my $single_quoted = 'This is a $fruit. \n (literal)';my $double_quoted = "This is an $fruit. \n (interpolated)";my $escaped_chars = "Path: C:\\Program Files\\My App\nPrice: \$100";
print "Single: $single_quoted\n";print "Double: $double_quoted"; # 注意:这里没有 \n,直接使用了字符串中的 \nprint "Escaped: $escaped_chars\n";输出:
Single: This is a $fruit. \n (literal)Double: This is an apple. (interpolated)Escaped: Path: C:\Program Files\My AppPrice: $100Perl 为标量提供了各种运算符。数值运算符(+、-、*、/、%、**)用于数字。字符串连接使用点运算符(.)。字符串重复运算符是 x。
#!/usr/bin/perluse strict;use warnings;
my $greeting = "Hello" . " " . "Perl!"; # 字符串连接my $sum = 10 + 5.5; # 数值相加(结果是 15.5)my $product = 3 * 7; # 数值相乘my $repeated_str = "Ha" x 3; # 字符串重复 ("HaHaHa")
my $mixed_concat = $greeting . $sum; # 数字被转换为字符串进行连接
print "Greeting: $greeting\n";print "Sum: $sum\n";print "Product: $product\n";print "Repeated: $repeated_str\n";print "Mixed: $mixed_concat\n";输出:
Greeting: Hello Perl!Sum: 15.5Product: 21Repeated: HaHaHaMixed: Hello Perl!15.5Perl 会根据所使用的运算符自动在字符串和数字之间进行转换。这被称为自动激活(auto-vivification)或 DWIM(Do What I Mean,做我所指)行为。要检查标量是否看起来像一个数字,可以使用 Scalar::Util 模块中的 looks_like_number 函数。
多行字符串(Here Documents)
Section titled “多行字符串(Here Documents)”对于较长的多行字符串,Here Documents 非常方便。它们以 << 开头,后跟一个分隔符标记,然后在后续行上是字符串内容,最后以该分隔符标记单独占一行结束。
#!/usr/bin/perluse strict;use warnings;
my $message_type = "Urgent";
my $email_body = <<"END_OF_EMAIL";To: recipient@example.comFrom: sender@example.comSubject: $message_type Message
This is the body of the email.It can span multiple lines.Best regards,The SenderEND_OF_EMAIL
print $email_body;
# 缩进的 here-doc (Perl 5.26+)my $indented_text = <<~"STOP"; This line is indented. So is this one. STOPprint "---\n$indented_text---";如果分隔符被引用(例如,<<"EOF"),其行为类似于双引号字符串(会发生内插)。如果未被引用(例如,<<EOF),其行为也类似于双引号。如果使用单引号(例如,<<'EOF'),则类似于单引号字符串(不发生内插)。在分隔符前使用 ~(Perl 5.26+)允许正文和结束标记缩进。
V-Strings(版本字符串 / 向量字符串)
Section titled “V-Strings(版本字符串 / 向量字符串)”v1.2.3 或 v65.66.67 形式的字面量是一个 V-String。它被解析为一个由指定序数(点分隔的数字)对应的字符组成的字符串。如果 v 后面只有一个数字(例如 v65),它被解释为一个具有该序数值的单个字符。如果没有点且数字多于一个(例如 v102.111.111),这种语法主要用于表示版本号,但 Perl 可能会将 v1.2.3 解析为 \x1\x2\x3。
历史上,V-Strings 旨在用于版本号。通过序数构造任意字符字符串(例如,用 v65.66.67 表示 “ABC”)的方式不如使用 chr(65) . chr(66) . chr(67) 或 "\x41\x42\x43" 常见。
#!/usr/bin/perluse strict;use warnings;use utf8; # 对于正确处理 Unicode 字符很重要use feature 'say';
my $version_string = v5.36.0;say "Version: $version_string"; # 通常字符串化后看起来像 "^X6\0"# 要获取预期的版本表示,最好这样处理:# printf "Version: %vd\n", $version_string; # 打印 5.36.0
my $char_A = v65;say "Character A (from v65): $char_A"; # 输出: A
my $hello_world_ords = v72.101.108.108.111.32.87.111.114.108.100;say "String from ordinals: $hello_world_ords"; # 输出: Hello World
# 现代方式打印版本对象:my $perl_version = $^V; # $^V 是一个保存 Perl 版本为 v-string 的特殊变量printf "Running Perl version: %vd\n", $perl_version; # 打印实际版本输出(版本表示可能因未使用 printf %vd 而略有不同):
Version: \x05(\x00Character A (from v65): AString from ordinals: Hello WorldRunning Perl version: 5.xx.y (actual version)Perl 提供了一些特殊字面量,代表程序当前的特定信息:
__FILE__:当前文件的名称。__LINE__:脚本中的当前行号。__PACKAGE__:当前包(命名空间)。__SUB__:对当前子例程(subroutine)的引用(Perl 5.16+)。__END__:在逻辑上结束脚本。__END__之后的任何文本都可以通过DATA文件句柄读取。
这些是标记(tokens),而不是变量,因此它们不能直接在双引号字符串中内插,需要进行连接。
#!/usr/bin/perluse strict;use warnings;use feature 'say';
sub show_literals { say "This code is in package: " . __PACKAGE__; say "Running from file: " . __FILE__; say "Currently at line: " . __LINE__; if (defined &${__SUB__}) { # 检查 __SUB__ 是否可用且已定义 say "Inside subroutine: " . ((__SUB__)->() ? (__SUB__)->() : 'N/A'); }}
show_literals();
say "End of main script logic.";
__END__This is data after __END__.It can be read via the DATA filehandle.输出(文件名和行号会有所不同):
This code is in package: mainRunning from file: ./your_script_name.plCurrently at line: 9Inside subroutine: main::show_literalsEnd of main script logic.