【问题标题】:Column formatting unix列格式化 unix
【发布时间】:2016-05-10 10:32:05
【问题描述】:

所以我遇到的问题是格式化列以提供更多空间,所以我不确定如何为列模式提供更多空间,以便所有内容都对齐。现在我的 awk 语句只是格式化它,以便每个字段都是分开的,这样没有中间名的人就不会搞砸了哈哈。

 $ cat file

1 Jackson, Bob D. C0001 book pizza apple 4.00 123as 
2 Filer, Jack C0002 happy apple hat 4.00 124ab 
3 Metro, Jim K. C0003 kindle pizza grape 4.00 125ac

那是原始文件,所以我使用下面的 awk 语句来分隔每一列,这样中间名就不会尝试将另一列分组到其中

$ echo "#  ""Name             ""LS     ""mode       ""food   ""item   ""num   ""list   "
$ echo "-  ""---------------  ""-----  ""---------  ""-------""-----  ""----  ""-----  "
$ awk -v OFS='~' '{$2=$2" "$3;$3=""} 
        NF==10{$2=$2" "$4;$4=""} 
         NF==9{$3=$3 OFS ""}1' file | column -ts~
#  Name             LS     mode       food   item   num   list   
-  ---------------  -----  ---------  -----  -----  ----  -----  
1  Jackson, Bob D.  C0001  book    pizza  apple  4.00  123as
2  Filer, Jack      C0002  happy   apple  hat    4.00  124ab
3  Metro, Jim K.    C0003  kindle  pizza  grape  4.00  125ac

所以我希望它按原样出现。如果您有更好的方法,那么只需在随意编辑时回显这些项目,但如果它很好,为什么它并不重要,我只需要最终输出看起来像这样谢谢!

#  Name             LS     mode       food   item   num   list   
-  ---------------  -----  ---------  -----  -----  ----  -----  
1  Jackson, Bob D.  C0001  book       pizza  apple  4.00  123as
2  Filer, Jack      C0002  happy      apple  hat    4.00  124ab
3  Metro, Jim K.    C0003  kindle     pizza  grape  4.00  125ac

【问题讨论】:

  • 您应该发布您的输入文件数据,而不是awk 语句的结果。
  • OK 添加了原文件 抱歉我发的时候没想到
  • 现在,问题已经很清楚了,并显示了足够的研究。至于解决方案,您可以使用我的answer中提到的printf
  • 现在我不必像在之前的代码中那样使用字段分隔符了吗?因为就像我一直对 Filer 的问题一样,Jack C0002 会尝试成为它的中间名?

标签: unix awk formatting


【解决方案1】:

awk 来救援!

我将以不同的方式为您解决名称问题,并展示如何使用 printf 进行格式化,您可以添加标题和其余字段以查找上面的答案。

    $ awk 'NF==9{for(i=NF;i>=4;i--) $(i+1)=$i; $4=""}
                {printf "%d %-15s %5s\n", $1,$2" "$3" "$4, $5}' file

1 Jackson, Bob D. C0001
2 Filer, Jack     C0002
3 Metro, Jim K.   C0003

【讨论】:

  • 完美的家伙,谢谢你再次来救我哈哈,这正是我要找的!
  • 现在有什么方法可以计算出我们应该等于多少 NF ?就像我们不知道没有中间首字母的人的名字有多长?
  • 这里假设它比完整的 10 个字段少一个。如果还有另一个缺失的字段,则没有其他方法。应在原始文件中正确设置字段分隔符(不是空格),以便正确识别字段和字段计数。缺乏这是您可以使用的启发式方法。
【解决方案2】:

我不会费心去弄清楚这个人有多少个名字。您知道最后 6 个字段是“值”,第一个字段是数字,剩下的就是名称。索引算法有点棘手但还不错:

awk '
    # too bad awk doesn't have a built-in join function
    function join(sepstr, array, len,       sep, i, result) {
        sep = ""
        result = ""
        for (i=1; i <= len; i++) {
            result = result sep array[i]
            sep = sepstr
        }
        return result
    }
    BEGIN {print "#:Name:LS:mode:food:item:num:list"}
    {
        delete result
        result[1] = $1
        for (i=1; i <= 6; i++) result[i+2] = $(NF-6+i)
        delete names
        len=0
        for (i=2; i <= NF-6; i++) {names[i-1] = $i; len++}
        result[2] = join(" ", names, len)
        print join(":", result, 8)
    }
' file | column -t -s:
#  Name             LS     mode    food   item   num   list
1  Jackson, Bob D.  C0001  book    pizza  apple  4.00  123as
2  Filer, Jack      C0002  happy   apple  hat    4.00  124ab
3  Metro, Jim K.    C0003  kindle  pizza  grape  4.00  125ac

如果您确实需要分隔符,请将column 输出通过管道传输到

perl -lpe 'if ($. == 2) {($line=$_) =~ s/(\S+.*?)($|  (?=\S))/ "-" x length($1) . $2 /ge; print $line}'

得到

#  Name             LS     mode    food   item   num   list
-  ---------------  -----  ------  -----  -----  ----  -----
1  Jackson, Bob D.  C0001  book    pizza  apple  4.00  123as
2  Filer, Jack      C0002  happy   apple  hat    4.00  124ab
3  Metro, Jim K.    C0003  kindle  pizza  grape  4.00  125ac

注意,如果你不依赖于 awk,perl 会更简洁。 Perl 的数组操作函数远远超出了 awk。如下所示,我们有 shift/unshift 从列表前面删除/添加元素,pop/push 从列表末尾删除/添加元素:

perl -lane '
    BEGIN {print "#:Name:LS:mode:food:item:num:list"}
    undef @res;
    unshift @res, pop @F for 1..6;
    $n = shift @F;
    unshift @res, $n, join(" ", @F);
    print join(":", @res)
' file | column -t -s:

【讨论】:

    【解决方案3】:

    printf 是你的朋友。

    示例

    awk '{ printf "%-30s %s \n", $1, $2 }' inputfile.txt
    

    在上面的示例中,第一列将左对齐 30 个字符。

    awk printf 支持的数据类型

    %i or d --Decimal
    %o --Octal
    %x --hex
    %c --ASCII number character
    %s --String
    %f --floating number
    

    填充选项

    -n --Pad n spaces on right hand side of a column.
    n --Pad n spaces on left hand side of a column.
    .m --Add zeros on left side.
    -n.m --Pad n spaces right hand side and add m zeros before that number.
    n.m --Pad n spaces left hand side and add m zeros before that.
    

    使用上面的细节,我们可以像这样重写awk语句

    awk 'BEGIN { format = "%d %-15s %5s %-9s %-5s %-5s %1.2d %5s \n"
                 printf format, "#", "Name", "LS", "mode","food","item","num   ","list"
                 printf format, "-","---------------","-----","---------","-----","-----","----","-----" }
               { printf format, $1, $2, $3, $4, $5, $6, $7,$8 }' inputfile.txt
    

    perl 解决方案

    $ perl -lane 'printf "%d%-15s%5s%-9s%-5s%-5s%-5s%1.2d%5s\n",@F' file 
    

    【讨论】:

      猜你喜欢
      • 2013-09-25
      • 2017-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多