将行转换为Bash中的列

时间:2016-04-26 10:58:27

标签: bash awk sed transpose

我在网上搜寻了解如何做我想做的事,但无济于事。我需要转置下面的数据......

Caption=C:
Description=Local Fixed Disk
DriveType=3
FreeSpace=41265664000
ProviderName=
Size=146056146944
VolumeName=
Caption=D:
Description=Local Fixed Disk
DriveType=3
FreeSpace=125067259904
ProviderName=
Size=1073738674176
VolumeName=Data
Caption=E:
Description=Removable Disk
DriveType=2
FreeSpace=
ProviderName=
Size=
VolumeName=

到表格布局,像这样......

Caption   Description        DriveType   FreeSpace     ProviderName   Size            VolumeName 
C:        Local Fixed Disk   3           41265664000                  146056146944     
D:        Local Fixed Disk   3           125067259904                 1073738674176   Data 
E:        Removable Disk     2   

bash。我一直在探索无数的awk脚本,但我似乎并不理解它们背后的逻辑:|

任何帮助将不胜感激。谢谢!

3 个答案:

答案 0 :(得分:1)

gawk

awk -v RS="Caption" -F"[=\n\"]" '
    NR==2{
        printf RS;
        for(i=3;i<=NF;i+=2){
            printf ":"$i
        };
        print ""
    };
    {
    for(i=2;i<=NF;i+=2){
        if ($i != "" ) printf ":"$i;
        else printf ": "
    };
    print ""}'  file | column -s":" -t

答案 1 :(得分:1)

您可以使用其他工具执行此操作,例如Perlpython

例如,在Perl中你可以使用它:

#!/usr/bin/perl -n
use Text::ASCIITable;

next unless /^(\w+)\s*=\s*(.*)$/;
$data{$1} = [] if not $data{$1};
push $data{$1}, $2;

END {
    $t = Text::ASCIITable->new();
    $t->setCols(keys %data);

    for my $i (0..@{$data{(keys %data)[0]}} - 1) {
        $t->addRow(map $data{$_}[$i], keys %data)
    }
    print $t;
}

您的数据可以在data.txt中,因此您可以写:

$ ./myscript.pl data.txt
.---------------------------------------------------------------------------------------------------.
| Caption | Size          | DriveType | VolumeName | FreeSpace    | Description      | ProviderName |
+---------+---------------+-----------+------------+--------------+------------------+--------------+
| C:      |  146056146944 |         3 |            |  41265664000 | Local Fixed Disk |              |
| D:      | 1073738674176 |         3 | Data       | 125067259904 | Local Fixed Disk |              |
| E:      |               |         2 |            |              | Removable Disk   |              |
'---------+---------------+-----------+------------+--------------+------------------+--------------'

此脚本适用于任何顺序的 N 列数。但是,如果列已知并且始终以相同的顺序显示,则代码可以简化为:

#!/usr/bin/perl -n
use Text::ASCIITable;

BEGIN {
    @columns = qw/Caption Description DriveType FreeSpace ProviderName Size VolumeName/;
    $t = Text::ASCIITable->new();
    $t->setCols(@columns);
    $re = join "\n", map "$_=(?<$_>.*)", @columns;
    undef $/;
}

$t->addRow(map $+{$_}, @columns) while(/$re/g);

END { print $t; }

如果你愿意,甚至可以在Python中使用:

#!/usr/bin/python
import sys
from terminaltables import AsciiTable
table_data = []
for row in ["Caption" + d for d in sys.stdin.read().split("Caption")[1:]]:
    table_data.append([column.split('=')[1] for column in row.split("\n")[:-1]])
    columns = [column.split('=')[0] for column in row.split("\n")[:-1]]

table_data.insert(0, columns)
print AsciiTable(table_data).table

答案 2 :(得分:0)

$ cat tst.awk
BEGIN { FS=OFS="=" }
{ hdr = hdr sep $1; data = data sep $2; sep=OFS }
$1=="VolumeName" { if (!c++) print hdr; print data; data=sep="" }

$ awk -f tst.awk file | column -s= -t
Caption  Description       DriveType  FreeSpace     ProviderName  Size           VolumeName
C:       Local Fixed Disk  3          41265664000                 146056146944
D:       Local Fixed Disk  3          125067259904                1073738674176  Data
E:       Removable Disk    2