【问题标题】:How can I clean up misaligned columns in text?如何清理文本中未对齐的列?
【发布时间】:2009-10-01 17:26:19
【问题描述】:

我有一个 C 程序,它输出两列,完全错位。未对齐的原因是第一列中单词的长度非常不同。

我在 vi 中打开了一个输出文件。如何快速对齐这两列?我可以使用 awk、perl、sed,而不仅仅是 vi (7.2) 工具集。另外,我们可以为超过两列的文件提供通用解决方案吗?

这里是示例文件

column1               column2
-------               -------
sdfsdfsddfsdfsdfsdfsd         343r5
dfgdfgdf             234
gdfgdfgdfgdfgf            645

【问题讨论】:

    标签: text


    【解决方案1】:

    大概您首先使用printf 来输出列。您可以在格式字符串中使用额外的修饰符来确保对齐。

    • 要打印特定宽度的列(右对齐),请在格式化标志之前添加宽度,例如,“%10s”将打印宽度为 10 的列。如果您的字符串长度超过 10 个字符,则该列会比你想要的长,所以选择一个最大值。如果字符串较短,则会用空格填充。
    • 要使列左对齐,请在前面放置一个 - 符号,例如“%-10s”。我个人喜欢左对齐字符串和右对齐数字。
    • 如果要打印地址,可以将填充字符从空格更改为以零开头的零:“%010x”。

    举一个更深入的例子:

    printf("%-30s %8s %8s\n", "Name", "Address", "Size");
    for (i = 0; i < length; ++i) {
        printf("%-30s %08x %8d\n", names[i], addresses[i], sizes[i]);
    

    这将像这样打印三列:

    Name                            Address     Size
    foo                            01234567      346
    bar                            9abcdef0     1024
    something-with-a-longer-name   0000abcd     2048
    

    【讨论】:

      【解决方案2】:

      要快速解决问题,请将其通过列管道:

      your_program | column -t
      

      如果您需要在列数据中包含空格,则使用“|”等字符分隔字段和:

      your_program | column -t -s "|"
      

      您可以使用任何字符作为分隔符并使用 -s 开关指定它。控制字符是可能的,但使用起来有点棘手。

      但正如 Jay 所说,您最好修复程序以正确格式化输出。

      【讨论】:

      • 您可以使用 Bash 的一个特性来轻松指定控制字符,例如 Tab:column -t -s $'\t'
      • 警告:列不喜欢“太长”的行,虽然 man column 提到了 2048 字节的限制,但实际上几百字节就足以扼杀它(在 Debian 8.3 上至少)。
      【解决方案3】:

      这是一个 awk 解决方案:c_prog | awk '{ printf("%- 40s %- 40s\n", $1, $2); }'

      【讨论】:

        【解决方案4】:

        如果您想在 Vim 中进行处理(而不是修复生成器),请安装 superb align plugin 并运行以下命令:

        ggVG
        \tsp
        

        第一个命令分解为gg(转到文件开头)、V(进入可视行模式)、G(转到文件末尾)。作为一个组合,它在视觉上选择整个文件。 \tsp 是在空白处对齐的 Align 映射。

        如果您更喜欢在: 命令行中执行操作,可以使用替代分隔符(例如###)并使用命令行对齐:

        :%s/\s\+/###/g
        :%Align ###
        :%s/### //g
        

        它更长,但您可能会发现它更合乎逻辑/更令人难忘。

        【讨论】:

          【解决方案5】:

          我用 Perl 写了一个小程序来解决这个问题。它也适用于多列。

          #!/usr/bin/perl
          use strict;
          use warnings;
          my $sep = 2;
          
          sub max {
              my ($a,$b) = @_;
              return $a > $b ? $a : $b;
          }
          
          my @rows;
          my $cols;
          my $max = 0;
          
          while (<>) {
              next if m/^\s*$/;
              my (@cols) = split m'\s+';
          
              for (@cols) {
                  $max = max($max, length);
              }
          
              $cols = @cols;
              push @rows, \@cols;
          }
          
          for (@rows) {
              my $str = join '', (('%-' . ($max+$sep) . 's') x $cols);
              $str .= "\n";
              printf $str, @$_;
          }
          

          【讨论】:

            【解决方案6】:

            我只是在另一个答案选项中添加了缺失:

            带有 M-x align-regexp、M-x align-string 等的 Emacs。在http://www.emacswiki.org/emacs/AlignCommands

            了解更多信息

            POSIX shell(可能是内置的)命令printf

            while read f1 f2 f3 tail; do printf "%10s %5s | %s" $f1 $f3 $tail; done <file.txt
            

            【讨论】:

              猜你喜欢
              • 2020-01-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-07-10
              • 2017-05-17
              • 2014-07-27
              • 2012-09-21
              • 1970-01-01
              相关资源
              最近更新 更多