2016-04-26 3 views
-1

Я тратил Интернет, чтобы понять, как делать то, что я хочу делать, но безрезультатно. Мне нужно перенести данные ниже ....Транспонирование строк в столбцы в Bash

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, но, похоже, я не понимаю логику, лежащую в их основе: |

Любая помощь будет оценена по достоинству. Спасибо!

+1

Зачем вам нужен использовать 'bash',' sed' или 'awk' здесь? Эти проблемы могут быть легко решены с помощью 'perl' или' python' – nowox

+0

'bash',' sed' и 'awk' - это только путь, который я начал. Если есть лучшие инструменты/решения, я с удовольствием поеду туда. –

ответ

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

Вы можете использовать другие инструменты, чтобы сделать это, такие как 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 ([email protected]{$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 
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 
Смежные вопросы