Satırları sütunlara dönüştürme


10

Bir hipervizörde çalışan VM'ler hakkında ayrıntılar içeren bir dosyam var. Bazı komutlar çalıştırıp çıktıyı bir dosyaya yönlendiriyoruz. Ve veriler aşağıdaki formatta mevcuttur.

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

Bu çıkış hipervizörden hipervizöre farklılık gösterir çünkü bazı hipervizörlerde 50 + vms çalışıyoruz. Yukarıdaki dosya, yalnızca 3 VM çalıştığımız hipervizörden sadece bir örnektir ve bu nedenle yeniden yönlendirilen dosyanın birkaç (N sayısı VM) hakkında bilgi içermesi beklenmektedir

Bu ayrıntıları awk / sed kullanarak veya bir kabuk komut dosyası kullanarak aşağıdaki biçimde almamız gerekir

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

Yanıtlar:


1

Dosyayı iki kez yürümek (büyük) bir sorun değilse (bellekte yalnızca bir satır depolar):

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

Hangi, genel bir alan sayısı için olurdu (dosyada birçok yürüyüş olabilir):

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

Ama gerçekten genel bir devrik için bu işe yarayacak:

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

Ve güzelleştirmek için (sekmeyi \talan ayırıcı olarak kullanarak ):

./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

Genel bir devrik için yukarıdaki kod tüm matrisi bellekte saklar.
Bu gerçekten büyük dosyalar için bir sorun olabilir.


Yeni metin için güncelleme.

Soruda yayınlanan yeni metni işlemek için, bence iki geçiş awk en iyi cevaptır. Alanlar var olduğu sürece bir geçiş üstbilgi alanı başlıklarını yazdırır. Bir sonraki awk geçişi yalnızca alan 2'yi basacaktır. Her iki durumda da, önde gelen ve arkadaki boşlukları (daha iyi biçimlendirme için) kaldırmak için bir yol ekledim.

#!/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')"

Çevresi { ... } | column -t -s "$(printf '%b' '\t')"güzel bir şekilde tüm tabloyu biçimlendirmektir.
Lütfen ksh, bash veya zsh "$(printf '%b' '\t')"ile değiştirilebileceğini unutmayın $'\t'.


8

Kullanılabilir rs(yeniden şekillendirme) yardımcı programınız varsa aşağıdakileri yapabilirsiniz:

rs -Tzc: < input.txt

Bu, dinamik sütun genişliklerine kadar bile çıktı biçimini tam olarak soruda belirtildiği gibi verir.

  • -T Girdi verilerini aktarır
  • -z sütunları her sütundaki maks. değerden uygun şekilde boyutlandırır
  • -c: giriş alanı ayırıcısı olarak iki nokta üst üste kullanır

Bu, keyfi olarak boyutlandırılmış tablolar için geçerlidir, örneğin:

$ 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
$ 

rsOS X (ve muhtemelen diğer BSD makinelerinde) varsayılan olarak kullanılabilir. Ubuntu'ya (ve debian ailesine) aşağıdakilerle kurulabilir:

sudo apt-get install rs

6

DÜZENLEME: Tek satırlık basit bir fordöngüde istediğiniz sayıda çıkış satırına genişletilebilir :

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

Orijinal cevap:

bashİşlem ikamesi kullanarak bunu tek astar olarak yapabilirsiniz:

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

-sSeçeneği pastebir anda her dosya birini işlemek yapar. Ayarlanan :sınırlayıcı , sonunda satırları hizalayarak formatı güzelleştirme seçeneği ile paste"yakalanır" .-scolumn

cutİki işlem ikameleri komutlar sırasıyla birinci alan ve ikinci alan çekin.

Girişte boş satır olup olmadığı önemli değil column -t -s:, çıktı ne olursa olsun çıktıyı temizler. (Soruda belirtilen orijinal girişte boş satırlar vardı, ancak o zamandan beri kaldırıldı. Yukarıdaki komut boş satırlardan bağımsız olarak çalışır.)

Girdi - yukarıdaki komutta "girdi" adlı dosyanın içeriği:

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

Çıktı:

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
Bu, iki çıkış satırı için çalışır, ancak daha fazla satır için kullanılmaz hale gelir.

2

Awk kullanarak anahtarı ve değeri saklayın ve sonunda yazdırın.

#!/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]
  }

Sadece koşmak awk -f ./script.awk ./input.txt


Cevabı dinamik olarak değiştirdi. Sadece dosya başına sadece 1 VM değerinde veri olmasını gerektirir.
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

Şununla gnu datamashve columnüzerinden util-linux:

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

Bu, ikiden fazla sütunla çalışır, ancak giriş dosyanızda boş satır olmadığını varsayar; arasında boş satırlar varsa (ilk giriş örneğinizde olduğu gibi) şöyle bir hata alırsınız:

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

bundan kaçınmak için aşağıdakileri işlemeden önce sıkmanız gerekir datamash:

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

Aksi takdirde, bu özel durumda (sadece iki sütun) zshve aynı column:

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

(${(f)"$(<infile)"})bir dizideki satırları okur; her öğenin ilk alanını ${(j;:;)list[@]%:*}birleştirir (ile :) ve her öğenin ikinci alanını ${(j;:;)list[@]#*:}birleştirir (ile :); bunların ikisi de yazdırılır, örneğin çıktı

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

daha sonra column -t -s:


0

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

Bu durumda Sanal Makine başına satır sayısı sabit olarak kodlanır - 11. Önceden saymak ve değişkene depolamak daha iyi olacaktır, daha sonra bu değişkeni kodda kullanın.

açıklama

  1. cat <(command 1) <(command 2)- <()yapı commandçıktıyı geçici bir dosya gibi gösterir. Bu nedenle, catiki dosyayı birleştirir ve daha da fazla yönlendirir.

    • komut 1 :, head -n 11 virtual.txt | cut -d: -f1bize gelecekteki sütun başlıklarını verir. Bir Sanal Makine girişi ilk on bir satırdır, headkomut almak için kullanılır. cutİki sütun bu girdiyi böler ve sadece ilkini yazdırın.
    • komut 2 : sed 's/.*: //' virtual.txt- bize gelecekteki sütun değerlerini verir. sedgereksiz tüm metinleri kaldırır ve yalnızca değerleri bırakır.
  2. xargs -d '\n' -n 11. Her girdi öğesi yeni satır ile sonlandırılır. Bu komut öğeleri alır ve her satıra 11 basar.

  3. column -t- güzel baskı yapan ekranlar için gereklidir. Çizgilerimizi bir tablo şeklinde görüntüler. Aksi takdirde, her satır farklı genişlikte olacaktır.

Çıktı

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

Dosyadaki satır ve sütunları değiştirmek datamashiçin transposeseçeneğini kullanın .

datamash -t: transpose < infile.txt

Transpose varsayılan olarak, girdinin her satırda aynı sayıda alana sahip olduğunu doğrular ve bir hatayla başarısız olursa, eksik değerlere izin vermek için katı modunu devre dışı bırakabilirsiniz. --no-strict

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

Ayrıca --fillereksik alan dolgu değerini ayarlamak için de kullanabilirsiniz :

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

elde edilen datamash manual


-5

verileriniz bir dizindeki ayrı dosyalardaysa aşağıdakileri kullanabilirsiniz:

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

değişken değerleriniz farklı uzunluklarda ise \t, printfsatırdaki (sekme) karakter sayısına masaj yapmanız gerekebilir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.