2009-10-02 1 views
10

У меня есть вход в следующем формате:Как «подушечка» строка переменной длины, чтобы иметь выровненную последний столбец


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

Я могу извлечь эти индивидуумы поля легко с использованием регулярного выражения /(\S+)\s+(\S+)\s+(\S+)\s+/. Я назвал их $time, $name и $number. Моя проблема заключается в том, что я хочу отобразить это так, чтобы $number идеально сочетался. Потому что $name может быть любой длины, что является лучшим решением для этого?

Я хотел бы, чтобы результат выглядел следующим образом. Обратите внимание, что мне нужно было использовать точки для выравнивания последнего поля, так как я не мог использовать пробел для этого, не знаю почему. 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 

Я думал о помещении $name в массив. И затем используйте функцию, чтобы найти ту, которая имеет самый длинный счетчик символов. Наконец, я бы выбрал более короткое имя, чтобы соответствовать самому длинному имени. Есть ли лучший и эффективный способ сделать это?

+0

Используйте опцию форматирования кода, чтобы указать, что шрифт фиксированной ширины и предварительная форматирование должны использоваться. :) – Amber

+0

Я просто делал это редактирование на своем телефоне, пока не понял, что это слишком сложно. –

+0

Являются ли цифры всегда по одной цифре? Если нет, что вы хотите сделать? –

ответ

19

Для форматирования, попробуйте использовать функцию sprintf, как в

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

(знак минус означает, что левый оправдает)

+0

спасибо! это именно то, что я искал. – qdog

4

Оно было дано кем-то 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; 

Вы можете изменить имена переменных, и он должен работать для вас.

+3

Ничего себе, люди по-прежнему используют форматы? Как очень perl 4 из вас :) – Ether

0

Что бы вы ни делали, вы будете иметь дело с двумя проходами - один, чтобы найти длину, одну для печати, используя эту длину в форматировании. Я бы пошел с ответом sprintf, уже предоставленным для форматирования, лично, просто меняя число в нем.

Точно, как вы выполняете эти два прохода, а зависит от того, откуда поступают данные - чтение файла дважды может быть более мудрым, чем предварительная обработка его в памяти, если файл огромен, но предлагаемое решение массива звучит хорошо меня.

2

Если вы не знаете максимальную ширину среднего поля, вам необходимо сделать два прохода над данными как @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

Посмотрите на Perl6::Form.

Это рекомендуемый подход при использовании format.Смотрите этот предыдущий Stack Overflow   ответ: What other languages have features and/or libraries similar to Perl's format?

Вот пример Perl6 :: Форма делает только то, что вы хотите с вашими данными:

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. Если ваши поля данных становятся больше заданных полей формы, тогда вы столкнетесь с проблемами форматирования (и то же самое относится и к решениям sprintf и format).

Это легко исправить в зависимости от ваших требований к выходным характеристикам. Например, если вы хотите поддерживать стабильность таблиц, то ...

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

... будет содержать слово для каждого столбца.

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

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

Итак, в приведенном выше примере «$ lineLength» сдвигается вправо с ведущими пробелами.

Смежные вопросы