Как я могу выровнять столбцы с Perf printf, когда значение может быть числом или строкой? - PullRequest
4 голосов
/ 15 апреля 2010

Я пытаюсь вывести документ, который выглядит следующим образом (подробнее на http://pastebin.com/dpBAY8Sb):

     10.1.1.1       100   <unknown>              <unknown>              <unknown>         <unknown>         <unknown>
72.12.148.186        94   Canada                 Hamilton               ON                43.250000        -79.833300   0.00
72.68.209.149        24   United States          Richmond Hill          NY                40.700500        -73.834500   611.32
 72.192.33.34         4   United States          Rocky Hill             CT                41.657800        -72.662700   657.48

Я не могу найти, как отформатировать вывод, у меня должна быть плавающая поза и форматирование расстояния между столбцами. Мой текущий код выглядит примерно так.

if (defined $longitude){
   printf FILE ("%-8s %.6f","",$longitude);
}else{
 $longitude = "<unknown>";
   printf FILE ("%-20s ",$longitude);
} 

Дополнительная "" сбрасывает весь столбец, и это выглядит так (подробнее на http://pastebin.com/kcwHyNwb).

10.1.1.1             100       <unknown>           <unknown>            <unknown>            <unknown>          <unknown>                 
72.12.148.186        94        Canada              Hamilton             ON                     43.250000         -79.833300           0.00
72.68.209.149        24        United States       Richmond Hill        NY                     40.700500         -73.834500           571.06

Ответы [ 3 ]

2 голосов
/ 15 апреля 2010

Хитрость в этих проблемах заключается в том, чтобы максимально уменьшить количество разветвлений и дублирования кода. Встроенный printf не такой уж особенный. Он принимает аргумент формата и список, так что вам просто нужно дать ему правильные вещи, а затем вызвать его один раз. Кроме того, вы можете быть более точным со своим чеком, используя что-то вроде Scalar :: Util * looks_like_number, чтобы ваши данные были ближе к тому, что вы ожидаете:

use Scalar::Util qw(looks_like_number);

while( <DATA> ) 
    {
    chomp(my $longitude = $_ );

    my( $format, @arguments ) = do {
        looks_like_number $longitude ?
            ( "|%-8s %.6f|\n", '', $longitude )
              :
            ( "| %16s|\n",        '<unknown>' )
        };

    printf $format, @arguments;
    }

__END__
1
2.12345678
undef
0

fred

Теперь у вас есть один printf, и вам не нужна дополнительная $longitude2 переменная. С printf вы можете поиграть в некоторые дополнительные трюки, чтобы вы могли автоматически изменять размер столбцов, но сейчас мы не будем об этом беспокоиться. :)

1 голос
/ 15 апреля 2010

Я думаю, что ваша строка формата для unknown немного отключена.

Вот мой образец:

foreach $longitude (1,2.12345678,undef) {
  if (defined $longitude){
     printf ("|%-8s %.6f|\n","",$longitude);
  }else{
    $longitude2 = "<unknown>";
    printf ("| %16s|\n",$longitude2);
  } 
}

И вывод (с " %16s" для неизвестного формата. Я добавил вертикальные полосы, чтобы четко видеть выравнивание):

|         1.000000|
|         2.123457|
|        <unknown>|

P.S. Если вы посмотрите на пример выравнивания по сравнению с тем, что вы создали на самом деле, кажется, что состояние <unknown> также может быть неправильно выровнено. Чтобы проверить, используйте тот же трюк, который я сделал выше, заключив строку формата для каждого поля в |, чтобы увидеть, где заканчивается одно поле и начинается другое.

0 голосов
/ 15 апреля 2010

Лично я передал бы их через тот же printf

 # You can choose prefered way of laying out the logic !
     $text = sprintf ("%.6f",$longitude); 
 # or 
     $text = '<unknown>' ;

, а затем

 printf ("| %16s|\n",$text);

Затем, если 16 становится 20, оба бита адаптируются на шаге.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...