在Bash中将行转换为列

在Bash中将行转换为列,bash,awk,sed,transpose,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=

我在互联网上搜寻,想弄清楚如何做我想做的事,但没有用。我需要转换下面的数据

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
脚本,但我似乎不太理解它们背后的逻辑:|


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

目瞪口呆

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
awk-v RS=“Caption”-F”[=\n\“]”
NR==2{
printf-RS;

对于(i=3;i您可以使用其他工具来执行此操作,例如
Perl
python

例如,在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; }

为什么需要在这里使用
bash
sed
awk
?这些问题可以通过
perl
python
bash
轻松解决,
sed
awk
正是我开始使用的路径。如果有更好的工具/解决方案,我很乐意这样做。
#!/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
$ 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