我正在尝试编辑文件的几行并创建具有所有修改的新文件
我的行不是段落格式,如下所示,
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
它们在行中的每个项目之间显然没有相等的间距,但是它们是按列对齐的。 我想将R3第3项从XA编辑为XAHBB 但无法保持列对齐
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
我的预期输出如下所示
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
在编辑文件时如何保持列对齐?
答案 0 :(得分:3)
这就是Text::Table的作用:
#!/usr/bin/perl
use warnings;
use strict;
use Text::Table;
my $table = 'Text::Table'->new;
while (<DATA>) {
my @RowEdit = split ' ';
if ($RowEdit[0] eq 'R3') {
$RowEdit[2] .= 'HBB';
}
$table->add(@RowEdit);
}
print $table;
print $. + 1, "\n";
__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
还请注意我所做的所有其他小更改:
$.
。/s
更改正则表达式中.
的行为。在不包含点的正则表达式中使用它是没有意义的。此外,如果只有一个与正则表达式匹配的字符串,则eq
可用于字符串等式-更易于阅读和运行。$_
作为第二个参数(如果未提供)。在$_
或grep
之外的任何地方键入map
都是一种代码味道-它值得一个名字,也可以不用它来编写。.=
运算符。答案 1 :(得分:2)
您可以使用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
输出为:
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
但是我认为Text :: Table解决方案更好:-)
答案 2 :(得分:0)
由于这是Perl最初为(Practical Extraction and Reporting Language)编写的任务之一,因此出于完整性考虑,还应提及良好的纯Perl格式,请参见man perlform
。例如
format STDOUT =
@<<<<< @ @<<<<, ....
$col1, $col2, $col3, ...
.
for my ... (...) {
# set $col1 .... and then
write
}