2009-10-02 41 views
10

Tôi có một đầu vào của các định dạng sau:Làm thế nào để "pad" một chuỗi chiều dài thay đổi để có một cột cuối cùng thẳng hàng


09:08:11  XXXXXXXXXXXXX 1.1.1.1   
09:09:03  YYYYYYYY 2.2.2.2   
09:12:37  ZZZZ 3.3.3.3 

tôi có thể trích xuất các cá nhân lĩnh vực dễ dàng sử dụng regex /(\S+)\s+(\S+)\s+(\S+)\s+/. Tôi đã đặt tên cho chúng là $time, $name$number. Vấn đề của tôi là tôi muốn hiển thị điều này để các $number căn chỉnh hoàn hảo. Bởi vì $name có thể có độ dài bất kỳ, giải pháp tốt nhất cho việc này là gì?

Tôi muốn đầu ra trông như thế này. Xin lưu ý rằng tôi đã phải sử dụng dấu chấm để căn chỉnh trường cuối cùng vì tôi không thể sử dụng phím cách để thực hiện việc này, không chắc chắn lý do. Anyhoo.


09:08:11  XXXXXXXXXXXXX 1.1.1.1   
09:09:03  YYYYYYYY   2.2.2.2   
09:12:37  ZZZZ    3.3.3.3 

Tôi nghĩ về việc đưa các $name vào một mảng. Và sau đó sử dụng một hàm để tìm một hàm có số ký tự dài nhất. Cuối cùng, tôi sẽ đặt tên ngắn hơn để khớp với tên dài nhất. Có cách nào tốt hơn và hiệu quả hơn để làm điều này không?

+0

Sử dụng tùy chọn Định dạng mã để chỉ định phông chữ cố định và định dạng trước nên được sử dụng. :) – Amber

+0

Tôi vừa tạo bản chỉnh sửa này trên điện thoại của mình, cho đến khi tôi nhận ra rằng nó quá khó. –

+0

Các con số có luôn là một chữ số không? Nếu không, bạn muốn làm gì? –

Trả lời

19

Đối với định dạng, hãy thử sử dụng sprintf chức năng, như trong

$line = sprintf "%-12s %-20s %-s\n", $time, $name, $number; 

(dấu trừ nghĩa trái-biện minh)

+0

cảm ơn bạn! điều này thật đúng với gì mà tôi đã tìm kiếm. – qdog

4

Nó được đưa ra bởi một người nào đó here:

my($name, $telephone, $stime); 

format Infos = 
@<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<< 
$name,    $telephone,   $stime 
. 

$~ = 'Infos'; 

($name, $telephone, $stime) = ('Name:', 'Telephone:', 'Start Time:'); 
write; 

($name, $telephone, $stime) = ('Mike Bax', 'tel-41596', 'Fri 8/22 13:31'); 
write; 

Bạn có thể thay đổi tên biến, và nó sẽ làm việc cho bạn.

+3

Ồ, mọi người vẫn sử dụng định dạng? Làm thế nào rất perl 4 của bạn :) – Ether

0

Dù bạn làm gì, bạn sẽ phải làm gì với hai đèo - một để tìm chiều dài, một để in, sử dụng độ dài đó trong định dạng. Tôi sẽ đi với câu trả lời sprintf đã được đưa ra cho các định dạng, cá nhân, chỉ cần thay đổi số lượng trong đó.

Chính xác cách bạn thực hiện hai lần thay đổi tùy thuộc vào nơi dữ liệu đến từ đâu - đọc một tệp hai lần có thể khôn ngoan hơn tiền xử lý nó vào bộ nhớ nếu tệp lớn, nhưng giải pháp mảng bạn đang đề xuất âm thanh tốt tôi.

2

Nếu bạn không biết chiều rộng tối đa của trường giữa, bạn sẽ phải thực hiện hai lần truyền dữ liệu là @ijw notes.

#!/usr/bin/perl 

use strict; 
use warnings; 

use Fcntl qw(:seek); 

my $max_length = 0; 
my $data_pos = tell DATA; 

while (my $line = <DATA>) { 
    last unless $line =~ /\S/; 
    my $name = (split ' ', $line)[1]; 
    my $name_length = length $name; 
    $max_length = $name_length if $name_length > $max_length; 
} 

seek DATA, $data_pos, SEEK_SET; 

while (my $line = <DATA>) { 
    last unless $line =~ /\S/; 
    my ($date, $name, $ip) = split ' ', $line; 
    printf "%s %-${max_length}s %s\n", $date, $name, $ip; 
} 

__DATA__ 
09:08:11  XXXXXXXXXXXXX 1.1.1.1 
09:09:03  YYYYYYYY 2.2.2.2 
09:12:37  ZZZZ 3.3.3.3 
3

Hãy xem Perl6::Form.

Đây là phương pháp được đề xuất khi sử dụng format.Xem stack   Overflow câu trả lời trước đây: What other languages have features and/or libraries similar to Perl's format?

Dưới đây là một ví dụ về Perl6 :: Mẫu làm chỉ là những gì bạn muốn với dữ liệu của bạn:

use Perl6::Form; 

my ($time, $name, $number); 

my @data = (
    [ qw(09:08:11 XXXXXXXXXXXXX 1.1.1.1) ], 
    [ qw(09:09:03 YYYYYYYY 2.2.2.2)  ], 
    [ qw(09:12:37 ZZZZ 3.3.3.3)   ], 
); 

for my $line (@data) { 
    push @$time, $line->[0]; 
    push @$name, $line->[1]; 
    push @$number, $line->[2]; 
} 

print form 
    '{[[[[[[} {[[[[[[[[[[[[[[[[[[[[} {[[[[[[}', 
    $time,  $name,     $number; 


NB. Nếu các trường dữ liệu của bạn trở nên lớn hơn các trường biểu mẫu được chỉ định thì bạn sẽ chạy vào các vấn đề định dạng (và điều tương tự cũng áp dụng cho các giải pháp định dạng và sprintf).

Dễ dàng khắc phục tùy thuộc vào yêu cầu đầu ra của bạn là gì. Ví dụ: nếu bạn muốn duy trì tính ổn định theo bảng thì ...

print form { layout => 'tabular' }, 
    '{[[[[[[} {[[[[[[[[[[[[[[[[[[[[} {[[[[[[}', 
    $time,  $name,     $number; 

... từ sẽ bao quanh mỗi cột cho bạn.

0
 $lineLength = length($line1); 
     write; 
} 
close FD1; 

format STDOUT = 
@>>>>> @* 
$lineLength,$line1 
. 
; 

Vì vậy, trong ví dụ trên, "$ lineLength" được đẩy sang phải với khoảng trắng phía trên.

Các vấn đề liên quan