如何在perl中打印文本文件的行时保持适当的列空间
我试图编辑我的文件的几行,并创建新的文件与所有修改 我的行不是段落格式,它看起来像下面这样如何在perl中打印文本文件的行时保持适当的列空间,perl,Perl,我试图编辑我的文件的几行,并创建新的文件与所有修改 我的行不是段落格式,它看起来像下面这样 R1 X XA 0i 1i H 0i R2 X XA 1i 1i H 0i R3 X XA 1i 1i H 0i R4 X XA 1i 1i H 0i R5 X XA 1i 1i H 0i R6 X XA 0i 0i X 0i 很明显,行中每个项目之间的间距不相等,但它们是以列为基础对齐的。 我想
R1 X XA 0i 1i H 0i
R2 X XA 1i 1i H 0i
R3 X XA 1i 1i H 0i
R4 X XA 1i 1i H 0i
R5 X XA 1i 1i H 0i
R6 X XA 0i 0i X 0i
很明显,行中每个项目之间的间距不相等,但它们是以列为基础对齐的。
我想编辑从XA到XAHBB的R3第三项
但无法保持柱对齐
my $cur_line_num = 1;
while(<Sourcefile>){
my @RowEdit = split (" ",$_);
if($RowEdit[0]=~ m/^R3$/s){
$RowEdit[2]="RowEdit[2]HBB"
}
my $curr_line = join(" ", @RowEdit)
print $newfile "curr_line\n";
$cur_line_num++;
}
print "$cur_line_num\n";
我的预期输出如下所示
R1 X XA 0i 1i H 0i
R2 X XA 1i 1i H 0i
R3 X XAHBB 1i 1i H 0i
R4 X XA 1i 1i H 0i
R5 X XA 1i 1i H 0i
R6 X XA 0i 0i X 0i
如何在编辑文件时保持列对齐?这就是它的用途:
#/usr/bin/perl
使用警告;
严格使用;
使用Text::Table;
my$table='Text::table'->新建;
而(){
我的@RowEdit=split';
如果($RowEdit[0]等式'R3'){
$RowEdit[2]。='HBB';
}
$table->add(@RowEdit);
}
打印$table;
打印美元+1、“\n”;
__资料__
R1 X XA 0i 1i H 0i
R2 X XA 1i 1i H 0i
R3 X XA 1i 1i H 0i
R4 X XA 1i 1i H 0i
R5 X XA 1i 1i H 0i
R6 X XA 0i 0i X 0i
还要注意我所做的所有其他小改动:
- 无需使用新变量来计算行数。Perl已经有了
$。
更改正则表达式中/s
的行为。在不包含点的正则表达式中使用它是没有意义的。此外,如果只有一个字符串与正则表达式匹配,
可以用于字符串相等-它更容易读取,运行更快eq
- 如果未提供任何参数,则使用
作为第二个参数。在$\uuu
或grep
之外的任何地方键入map
$\ucode>都是一种代码气味——要么是值得命名的东西,要么可以不用它来书写
- 要附加字符串,可以使用
运算符=
printf()执行此操作。但是您需要对数据进行两次遍历(因为在看到每个数据记录之前,无法知道最宽的列宽是多少)
像这样的事情似乎起到了作用
#!/usr/bin/perl
use strict;
use warnings;
my @widths; # Store the max widths for each column
my @data; # Store the actual data
while (<DATA>) {
my @row;
# Use the first line to initialise the @widths array
if ($. == 1) {
@row = /(\S+\s*)/g;
@widths = map { length() - 1} @row; # Subtract 1 for gutter
@row = map { s/\s+$//; $_ } @row; # Remove trailing whitespace
} else {
@row = split;
}
# Split the data
my @row = split;
# Store the split data
push @data, \@row;
# Make the (optional) transformation
$row[2] .= 'HBB' if $row[0] eq 'R3';
# Look at each column in this row of data and
# compare it to the widest data that we've previously
# seen in that column.
for my $i (0 .. $#row) {
$widths[$i] = length $row[$i]
if length $row[$i] > ($widths[$i] // 0);
}
}
# Create a printf output format using the column
# widths we've stored in @widths
my $fmt = join ' ', map { "%-${_}s" } @widths;
# Use printf to display each line of data.
printf "$fmt\n", @$_ for @data;
__DATA__
R1 X XA 0i 1i H 0i
R2 X XA 1i 1i H 0i
R3 X XA 1i 1i H 0i
R4 X XA 1i 1i H 0i
R5 X XA 1i 1i H 0i
R6 X XA 0i 0i X 0i
但是我认为Text::Table解决方案更好:-)因为这是Perl最初为()编写的任务之一,那么为了完整性,还应该提到好的ol'plain Perl格式,请参见man perlform
。例如
format STDOUT =
@<<<<< @ @<<<<, ....
$col1, $col2, $col3, ...
.
for my ... (...) {
# set $col1 .... and then
write
}
格式标准输出=
@有没有不使用Text::Table扩展就可以做到这一点的方法?使用基本perl命令,您可以随时阅读的源代码-只需单击。sprintf
和format
提供了类似的功能,但它们本质上不是动态的。您必须提前选择列宽(尽管您可能会“检测”列中最宽的单元格,并使用它),我正在将此数据从文件中打印到其他文件。willsprintf
解决方案使用此场景@Sobrique
#!/usr/bin/perl
use strict;
use warnings;
my @widths; # Store the max widths for each column
my @data; # Store the actual data
while (<DATA>) {
my @row;
# Use the first line to initialise the @widths array
if ($. == 1) {
@row = /(\S+\s*)/g;
@widths = map { length() - 1} @row; # Subtract 1 for gutter
@row = map { s/\s+$//; $_ } @row; # Remove trailing whitespace
} else {
@row = split;
}
# Split the data
my @row = split;
# Store the split data
push @data, \@row;
# Make the (optional) transformation
$row[2] .= 'HBB' if $row[0] eq 'R3';
# Look at each column in this row of data and
# compare it to the widest data that we've previously
# seen in that column.
for my $i (0 .. $#row) {
$widths[$i] = length $row[$i]
if length $row[$i] > ($widths[$i] // 0);
}
}
# Create a printf output format using the column
# widths we've stored in @widths
my $fmt = join ' ', map { "%-${_}s" } @widths;
# Use printf to display each line of data.
printf "$fmt\n", @$_ for @data;
__DATA__
R1 X XA 0i 1i H 0i
R2 X XA 1i 1i H 0i
R3 X XA 1i 1i H 0i
R4 X XA 1i 1i H 0i
R5 X XA 1i 1i H 0i
R6 X XA 0i 0i X 0i
R1 X XA 0i 1i H 0i
R2 X XA 1i 1i H 0i
R3 X XAHBB 1i 1i H 0i
R4 X XA 1i 1i H 0i
R5 X XA 1i 1i H 0i
R6 X XA 0i 0i X 0i
format STDOUT =
@<<<<< @ @<<<<, ....
$col1, $col2, $col3, ...
.
for my ... (...) {
# set $col1 .... and then
write
}