Ubah baris menjadi kolom


10

Saya memiliki file yang menyertakan detail tentang VM yang berjalan di hypervisor. Kami menjalankan beberapa perintah dan mengarahkan output ke file. Dan data tersedia dalam format di bawah ini.

Virtual Machine : OL6U5
        ID     : 0004fb00000600003da8ce6948c441bb
        Status : Running
        Memory : 65536
        Uptime : 17835 Minutes
        Server : MyOVS1.vmorld.com
        Pool   : HA-POOL
        HA Mode: false
        VCPU   : 16
        Type   : Xen PVM
        OS     : Oracle Linux 6
Virtual Machine : OL6U6
        ID     : 0004fb00000600003da8ce6948c441bc
        Status : Running
        Memory : 65536
        Uptime : 17565 Minutes
        Server : MyOVS2.vmorld.com
        Pool   : NON-HA-POOL
        HA Mode: false
        VCPU   : 16
        Type   : Xen PVM
        OS     : Oracle Linux 6
Virtual Machine : OL6U7
        ID     : 0004fb00000600003da8ce6948c441bd
        Status : Running
        Memory : 65536
        Uptime : 17835 Minutes
        Server : MyOVS1.vmorld.com
        Pool   : HA-POOL
        HA Mode: false
        VCPU   : 16
        Type   : Xen PVM
        OS     : Oracle Linux 6

Output ini berbeda dari hypervisor ke hypervisor karena pada beberapa hypervisor kami memiliki 50+ vms berjalan. File di atas hanyalah sebuah contoh dari hypervisor di mana kami hanya menjalankan 3 VM dan karenanya file yang dialihkan diharapkan berisi informasi tentang beberapa (sejumlah N VM)

Kita perlu mendapatkan detail ini dalam format di bawah ini menggunakan awk / sed atau dengan skrip shell

Virtual_Machine  ID                                Status   Memory  Uptime  Server              Pool        HA     VCPU  Type     OS
OL6U5            0004fb00000600003da8ce6948c441bb  Running  65536   17835   MyOVS1.vmworld.com  HA-POOL     false  16    Xen PVM  Oracle Linux 6
OL6U6            0004fb00000600003da8ce6948c441bc  Running  65536   17565   MyOVS2.vmworld.com  NON-HA-POOL     false  16    Xen PVM  Oracle Linux 6
OL6U5            0004fb00000600003da8ce6948c441bd  Running  65536   17835   MyOVS1.vmworld.com  HA-POOL     false  16    Xen PVM  Oracle Linux 6

2
Kemungkinan duplikat dari Baris ke konversi kolom file
αғsнιη

Jawaban:


1

Jika berjalan file dua kali bukan masalah (besar) (hanya akan menyimpan satu baris dalam memori):

awk -F : '{printf("%s\t ", $1)}' infile
echo
awk -F : '{printf("%s\t ", $2)}' infile

Yang, untuk hitungan bidang umum akan (yang bisa memiliki banyak lapisan file):

#!/bin/bash
rowcount=2
for (( i=1; i<=rowcount; i++ )); do
    awk -v i="$i" -F : '{printf("%s\t ", $i)}' infile
    echo
done

Tetapi untuk transpos yang benar-benar umum, ini akan bekerja:

awk '$0!~/^$/{    i++;
                  split($0,arr,":");
                  for (j in arr) {
                      out[i,j]=arr[j];
                      if (maxr<j){ maxr=j} # max number of output rows.
                  }
            }
    END {
        maxc=i                             # max number of output columns.
        for     (j=1; j<=maxr; j++) {
            for (i=1; i<=maxc; i++) {
                printf( "%s\t", out[i,j])  # out field separator.
            }
            printf( "%s\n","" )
        }
    }' infile

Dan untuk membuatnya cantik (menggunakan tab \tsebagai pemisah bidang):

./script | |column -t -s $'\t'

Virtual_Machine  ID                                Status   Memory  Uptime  Server              Pool     HA     VCPU  Type     OS
OL6U7            0004fb00000600003da8ce6948c441bd  Running  65536   17103   MyOVS1.vmworld.com  HA-POOL  false  16    Xen PVM  Oracle Linux 6

Kode di atas untuk transpose umum akan menyimpan seluruh matriks dalam memori.
Itu bisa menjadi masalah untuk file yang sangat besar.


Perbarui untuk teks baru.

Untuk memproses teks baru yang diposting dalam pertanyaan itu, bagi saya tampaknya dua lulus awk adalah jawaban terbaik. Satu pass, sesingkat field yang ada, akan mencetak judul field header. Awk pass berikutnya hanya akan mencetak bidang 2. Dalam kedua kasus, saya menambahkan cara untuk menghapus spasi awal dan akhir (untuk pemformatan yang lebih baik).

#!/bin/bash
{
awk -F: 'BEGIN{ sl="Virtual Machine"}
         $1~sl && head == 1 { head=0; exit 0}
         $1~sl && head == 0 { head=1; }
         head == 1 {
             gsub(/^[ \t]+/,"",$1);   # remove leading  spaces
             gsub(/[ \t]+$/,"",$1);   # remove trailing spaces
             printf( "%s\t", $1)
         }
         ' infile
#echo
awk -F: 'BEGIN { sl="Virtual Machine"}
         $1~sl { printf( "%s\n", "") }
         {
             gsub(/^[ \t]+/,"",$2);   # remove leading  spaces
             gsub(/[ \t]+$/,"",$2);   # remove trailing spaces
             printf( "%s\t", $2)
         }
         ' infile
echo
} | column -t -s "$(printf '%b' '\t')"

Sekitarnya { ... } | column -t -s "$(printf '%b' '\t')"adalah untuk memformat seluruh tabel dengan cara yang cantik.
Harap dicatat bahwa "$(printf '%b' '\t')"bisa diganti dengan $'\t'di ksh, bash, atau zsh.


8

Jika Anda memiliki rsutilitas (membentuk kembali) yang tersedia, Anda dapat melakukan hal berikut:

rs -Tzc: < input.txt

Ini memberikan format output persis seperti yang ditentukan dalam pertanyaan, bahkan hingga lebar kolom dinamis.

  • -T Transpos data input
  • -z ukuran kolom dengan tepat dari maks di setiap kolom
  • -c: menggunakan titik dua sebagai pemisah bidang input

Ini berfungsi untuk tabel berukuran sewenang-wenang, misalnya:

$ echo "Name:Alice:Bob:Carol
Age:12:34:56
Eyecolour:Brown:Black:Blue" | rs -Tzc: 
Name   Age  Eyecolour
Alice  12   Brown
Bob    34   Black
Carol  56   Blue
$ 

rstersedia secara default pada OS X (dan kemungkinan mesin BSD lainnya). Itu dapat diinstal di Ubuntu (dan keluarga debian) dengan:

sudo apt-get install rs

6

EDIT: Dapat diperluas ke sejumlah baris output, dalam satu forlingkaran sederhana:

for ((i=1;i<=2;i++)); do cut -d: -f "$i" input | paste -sd: ; done | column -t -s:

Jawaban asli:

Anda bisa melakukan ini sebagai satu-liner menggunakan bashsubtitusi proses:

paste -sd: <(cut -d: -f1 input) <(cut -d: -f2 input) | column -t -s:

The -spilihan untuk pastemerek itu menangani setiap satu file pada satu waktu. The :pembatas ditetapkan dalam pasteadalah "tertangkap" oleh -spilihan untuk columndi akhir, untuk cukup sampai format dengan membuat bidang berbaris.

The cutperintah dalam dua substitusi proses menarik keluar field pertama dan kolom kedua, masing-masing.

Apakah ada garis kosong di input atau tidak, tidak masalah, karena column -t -s:akan membersihkan output terlepas. (Ada baris kosong di input asli yang ditentukan dalam pertanyaan, tetapi sejak itu telah dihapus. Perintah di atas berfungsi terlepas dari baris kosong.)

Input - isi file bernama "input" pada perintah di atas:

Virtual_Machine:OL6U7

ID:0004fb00000600003da8ce6948c441bd

Status:Running

Memory:65536

Uptime:17103

Server:MyOVS1.vmworld.com

Pool:HA-POOL

HA:false

VCPU:16

Type:Xen PVM

OS:Oracle Linux 6

Keluaran:

Virtual_Machine  ID                                Status   Memory  Uptime  Server              Pool     HA     VCPU  Type     OS
OL6U7            0004fb00000600003da8ce6948c441bd  Running  65536   17103   MyOVS1.vmworld.com  HA-POOL  false  16    Xen PVM  Oracle Linux 6

2
Ini berfungsi untuk dua baris output, tetapi untuk lebih banyak baris menjadi sulit digunakan.

2

Menggunakan awk, simpan kunci dan nilai dan cetak pada akhirnya.

#!/usr/bin/awk -f
BEGIN {
  CNT=0
  FS=":"
}

{
  HDR[CNT]=$1;
  ENTRY[CNT]=$2;
  CNT++;
}

END {
  for (x = 0; x < CNT; x++)
    printf "%s\t",HDR[x]

  print""

  for (x = 0; x < CNT; x++)
    printf "%s\t",ENTRY[x]
  }

Yang baru saja lari awk -f ./script.awk ./input.txt


Mengubah jawaban menjadi dinamis. Hanya membutuhkan hanya ada 1 VM nilai data per file.
jecxjo

1
declare -a COLS
declare -a DATA
while IFS=':' read -ra fields; do
   COLS+=("${fields[0]}")
   DATA+=("${fields[1]}")
done < <( cat /path/to/input.txt)

HEADER=""
DATA=""
for i in $(seq 0 $((${#fields[@]}-1)); do
    HEADER="${HEADER}${COLS[$i]} "
    DATA="${DATA}${COLS[$i]} "
done
echo $HEADER
echo $DATA

1

Dengan gnu datamashdan columndari util-linux:

datamash -t: transpose <infile | column -t -s:

Ini berfungsi dengan lebih dari dua kolom tetapi mengasumsikan tidak ada baris kosong di file input Anda; dengan baris kosong di antara (seperti pada sampel input awal Anda), Anda akan mendapatkan kesalahan seperti:

datamash: transpose input error: line 2 has 0 fields (previous lines had 2);

jadi untuk menghindari itu Anda harus memerasnya sebelum diproses dengan datamash:

tr -s \\n <infile | datamash -t: transpose | column -t -s:

Kalau tidak, dalam kasus khusus ini (hanya dua kolom), dengan zshdan yang sama column:

list=(${(f)"$(<infile)"})
printf %s\\n ${(j;:;)list[@]%:*} ${(j;:;)list[@]#*:} | column -t -s:

(${(f)"$(<infile)"})membaca baris dalam array; ${(j;:;)list[@]%:*}bergabung (dengan :) bidang pertama dari setiap elemen dan ${(j;:;)list[@]#*:}bergabung (lagi dengan :) bidang kedua dari setiap elemen; keduanya dicetak, misalnya hasilnya

Virtual_Machine:ID:Status:Memory:Uptime:Server:Pool:HA:VCPU:Type:OS
OL6U7:0004fb00000600003da8ce6948c441bd:Running:65536:17103:MyOVS1.vmworld.com:HA-POOL:false:16:Xen PVM:Oracle Linux 6

yang kemudian disalurkan ke column -t -s:


0

cat <(head -n 11 virtual.txt | cut -d: -f1) <(sed 's/.*: //' virtual.txt) | xargs -d '\n' -n 11 | column -t

Jumlah baris per Mesin Virtual hardcoded dalam kasus ini - 11. Akan lebih baik menghitungnya terlebih dahulu dan menyimpannya ke dalam variabel, kemudian gunakan variabel ini dalam kode.

Penjelasan

  1. cat <(command 1) <(command 2)- <()konstruksi membuat commandoutput muncul seperti file sementara. Oleh karena itu, catgabungkan dua file dan pipa itu lebih lanjut.

    • perintah 1 : head -n 11 virtual.txt | cut -d: -f1, memberi kita header kolom masa depan. Entri satu Mesin Virtual adalah sebelas baris pertama, headperintah digunakan untuk mendapatkannya. The cutmembagi entri ini ke dua kolom dan mencetak satu-satunya pertama.
    • perintah 2 : sed 's/.*: //' virtual.txt- memberi kita nilai kolom di masa mendatang. sedmenghapus semua teks yang tidak dibutuhkan dan hanya menyisakan nilai.
  2. xargs -d '\n' -n 11. Setiap item input diakhiri oleh baris baru. Perintah ini mendapat item dan mencetaknya dengan 11 per baris.

  3. column -t- diperlukan untuk tampilan pencetakan yang cantik. Ini menampilkan garis kami dalam bentuk tabel. Jika tidak, setiap baris akan memiliki lebar yang berbeda.

Keluaran

Virtual  Machine                           ID       Status  Memory  Uptime   Server             Pool         HA     Mode  VCPU  Type  OS
OL6U5    0004fb00000600003da8ce6948c441bb  Running  65536   17835   Minutes  MyOVS1.vmorld.com  HA-POOL      false  16    Xen   PVM   Oracle  Linux  6
OL6U6    0004fb00000600003da8ce6948c441bc  Running  65536   17565   Minutes  MyOVS2.vmorld.com  NON-HA-POOL  false  16    Xen   PVM   Oracle  Linux  6
OL6U7    0004fb00000600003da8ce6948c441bd  Running  65536   17835   Minutes  MyOVS1.vmorld.com  HA-POOL      false  16    Xen   PVM   Oracle  Linux  6

0

Gunakan datamashdan transposepilihannya untuk menukar baris dan kolom dalam file.

datamash -t: transpose < infile.txt

Secara default, transpos memverifikasi input memiliki jumlah bidang yang sama di setiap baris, dan gagal dengan kesalahan sebaliknya dan Anda dapat menonaktifkan mode ketat untuk memungkinkan nilai yang hilang oleh --no-strict

datamash -t: --no-strict transpose < infile.txt

Anda juga dapat menggunakan --filleruntuk mengatur nilai pengisi bidang yang hilang:

datamash -t: --no-strict --filler " " transpose < infile.txt

berasal dari datamash manual


-5

jika data Anda berada di file terpisah di direktori, Anda dapat menggunakan:

for file in $(ls $DIRECTORY)
do
  cat ${file} | while read line
  do
    value=$(echo $line | cut -d: -f2-)
    printf "%s\t" "${value}" >> bigfile
  done
  echo " " >> bigfile
done

Anda mungkin perlu memijat jumlah \tkarakter (tab) di printftelepon jika nilai variabel Anda memiliki panjang yang berbeda.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.