Perl 格式化
Perl - 格式化 (报告生成)
Section titled “Perl - 格式化 (报告生成)”重要提示: Perl 中用于报告生成的 format 和 write 功能在很大程度上被视为传统 (legacy) 功能。虽然它们是 Perl 核心的一部分,但现代 Perl 开发绝大多数倾向于使用模板引擎 (templating engines)(例如 Template Toolkit、Text::Template、Mojo::Template)来生成文本报告、HTML 或其他结构化文本输出。这些引擎提供了更大的灵活性、更强大的功能和更好的可维护性。本节介绍 Perl 的格式化功能是为了完整性,但在新项目中通常不鼓励使用它们。
Perl 的 format 功能允许您定义模板来生成简单的固定列报告。您定义一个格式,然后使用 write 关键字根据该模板输出数据。
使用 format 关键字声明一个格式,后跟一个名称(通常与文件句柄名称绑定),一个等号,然后是定义布局的行,最后以单独一行上的句点 (.) 结束。
语法:
format FormatName =field_line_1value_line_1_var1, value_line_1_var2, ...field_line_2value_line_2_var1, value_line_2_var2, ....FormatName:格式的名称。默认情况下,Perl 会查找与当前输出文件句柄同名的格式(例如,如果打印到标准输出,则查找STDOUT)。field_line:包含字面文本和图片字段 (picture fields)(占位符 fieldholders),它们定义了如何格式化值。value_line:变量或表达式的列表,其值将被插入到前面field_line中的占位符中。
占位符 (图片字段):
Section titled “占位符 (图片字段):”占位符指定了数据在 field_line 中的位置和格式化方式。
@<<<<: 左对齐文本字段。<的数量加上@决定了字段宽度。@>>>>: 右对齐文本字段。@||||: 居中文本字段。@###.##: 数值字段。#代表数字位置。.是小数点。输出是右对齐的。@*: 多行文本字段。用于可能包含换行符的值。值会被打印出来,如果它没有填满当前行,format处理会在下一行继续,打印剩余的值。
格式定义的示例:
#!/usr/bin/env perluse strict;use warnings;
# 将被格式使用的变量our ($name, $age, $salary);
format EMPLOYEE_RECORD ======================================Name: @<<<<<<<<<<<<<<<<<<<<< Age: @<<$name, $ageSalary: @#####.##$salary-------------------------------------.在此示例中,$name 将在 25 个字符宽的字段(包括 @)中左对齐,$age 在 2 个字符宽的字段中,$salary 格式化为小数点前最多 5 位数字、小数点后 2 位数字的数值。
使用 write 输出格式化内容
Section titled “使用 write 输出格式化内容”write 关键字使用定义的格式输出数据。write 将输出发送到当前选定的文件句柄(参见 select())。要使用特定的格式,您可以使用特殊变量 $~(如果激活了 use English;,则使用 $FORMAT_NAME)将其与文件句柄关联。
#!/usr/bin/env perluse strict;use warnings;
# 声明将被格式使用的包变量our ($name, $age, $salary);
# 定义格式(同上)format EMPLOYEE_RECORD ======================================Name: @<<<<<<<<<<<<<<<<<<<<< Age: @<<$name, $ageSalary: @#####.##$salary-------------------------------------.
# 选择 STDOUT 作为 write 的输出文件句柄select(STDOUT);
# 将 EMPLOYEE_RECORD 格式与 STDOUT 关联$~ = "EMPLOYEE_RECORD";
# 报告数据my @employees = ( { name => "Alice Wonderland", age => 30, salary => 55000.75 }, { name => "Bob The Builder", age => 42, salary => 62000.50 }, { name => "Charlie Brown", age => 8, salary => 10.00 },);
foreach my $emp_data (@employees) { # 为格式使用的包变量赋值 $name = $emp_data->{name}; $age = $emp_data->{age}; $salary = $emp_data->{salary};
write; # 使用 EMPLOYEE_RECORD 格式将一条记录输出到 STDOUT}执行上述代码将产生:
=====================================Name: Alice Wonderland Age: 30Salary: 55000.75-------------------------------------=====================================Name: Bob The Builder Age: 42Salary: 62000.50-------------------------------------=====================================Name: Charlie Brown Age: 8Salary: 10.00-------------------------------------您可以定义一个页眉格式,它将在每页的顶部打印。此页眉格式的名称通常是 FILEHANDLE_TOP(例如 STDOUT_TOP)。您可以将页眉格式的名称赋给特殊变量 $^(如果激活了 use English;,则使用 $FORMAT_TOP_NAME)。
#!/usr/bin/env perluse strict;use warnings;
our ($name, $age, $salary); # 用于 EMPLOYEE_RECORDour ($page_num); # 用于 STDOUT_TOP
format STDOUT_TOP =Employee Report Page: @< $page_num----------------------------------------------------------Name Age Salary----------------------------------------------------------.
format EMPLOYEE_RECORD =@<<<<<<<<<<<<<<<<<<<<<<< @<< @##########.##$name, $age, $salary.
select(STDOUT);$~ = "EMPLOYEE_RECORD";$^ = "STDOUT_TOP"; # 设置页眉格式
# 模拟多名员工,以可能跨页显示(如果页长设置得较小)my @employees_data = ( { name => "Alice", age => 30, salary => 55000 }, { name => "Bob", age => 42, salary => 62000 }, # ... 添加更多员工以查看分页(如果 $= 设置得较小));
$page_num = 0; # 初始化页码,将由 $% 或手动更新
foreach my $emp_data (@employees_data) { # 在每次 write 之前,Perl 会检查是否需要新页。 # 如果需要,它会递增 $FORMAT_PAGE_NUMBER ($%) 并打印 _TOP 格式。 # 我们需要确保 $page_num 反映这一点,以便在页眉中使用。 $page_num = $%; # $FORMAT_PAGE_NUMBER if ($FORMAT_LINES_LEFT <= 3) { # 检查是否接近底部,页面分隔的启发式判断 $page_num++; # 如果需要,手动预判,或依赖 write 之前的 $% }
$name = $emp_data->{name}; $age = $emp_data->{age}; $salary = $emp_data->{salary}; write;}分页:页码和每页行数
Section titled “分页:页码和每页行数”使用格式化功能时,Perl 在一定程度上会自动处理分页。
$%(或$FORMAT_PAGE_NUMBER):包含当前页码。当发生分页时会自动递增。$=(或$FORMAT_LINES_PER_PAGE):指定每页可打印的行数。默认值为 60。您可以设置此变量来控制页长。$-(或$FORMAT_LINES_LEFT):包含当前页面剩余的行数。当此值达到 0(或由于多行字段而小于 0)时,会开始新页,打印_TOP格式,并将$-重置为$=。
要将页码包含在您的页眉中(如上面的 STDOUT_TOP 示例),请在页眉格式的值行中使用 $%。
format STDOUT_TOP =Employee Report Page @<<< $%------------------------------------Name Age Salary------------------------------------.Perl 没有与页眉的 $^ 相对应的页脚自动机制。如果您需要页脚,必须手动实现。这通常需要在每次 write 之前检查 $-(剩余行数)。如果 $- 太低,以至于下一条记录(加上页脚)无法容纳,您可以使用单独的 format 定义打印页脚,然后手动触发分页(例如,通过打印换行符直到 $- 为 0,或通过写入一个特殊的填充页面的空白记录),或者打印页脚后再打印新页的页眉。
format EMPLOYEE_FOOTER =End of Page @<. $%====================================.然后您将有条件地调用 write EMPLOYEE_FOOTER;。
如前所述,对于任何需要报告生成或文本模板的新开发,请考虑使用现代的 CPAN 模块,如 Template Toolkit、Text::Template 或其他提供远超 Perl 内置格式系统功能的模块,并且更易于维护。