J'ai un fichier qui inclut des détails sur les VMS exécutant dans un hyperviseur. Nous exécutons une commande et redirigeons la sortie dans un fichier. Et les données sont disponibles dans le format ci-dessous.
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
Cette sortie diffère de l'hyperviseur à l'hyperviseur depuis sur certains hyperviseurs que nous avons 50 + VMS fonctionnant. Le fichier ci-dessus est un exemple de l'hyperviseur où nous n'avons que 3 VMS fonctionnant et que le fichier redirigé devrait donc contenir des informations sur plusieurs (N Nombre de VMS).
Nous devons obtenir ces informations dans le format ci-dessous à l'aide de AWK/SED ou d'un script 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
Si vous marchez deux fois le fichier n'est pas un (gros) problème (stockera une seule ligne en mémoire):
awk -F : '{printf("%s\t ", $1)}' infile
echo
awk -F : '{printf("%s\t ", $2)}' infile
Qui, pour qu'un nombre général de champs serait (qui pourrait avoir de nombreuses promenades du fichier):
#!/bin/bash
rowcount=2
for (( i=1; i<=rowcount; i++ )); do
awk -v i="$i" -F : '{printf("%s\t ", $i)}' infile
echo
done
Mais pour une transposition vraiment générale, cela fonctionnera:
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
Et pour le faire jolie (à l'aide de l'onglet \t
Comme séparateur de champ):
./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
Le code ci-dessus pour une transposition générale stockera toute la matrice en mémoire.
[.____] Cela pourrait être un problème pour des fichiers vraiment gros.
Pour traiter le nouveau texte publié dans la question, il me semble que deux laissez-passer d'AWK sont la meilleure réponse. Un passage, aussi court que des champs existent, imprimera les titres de champ d'en-tête. Le prochain passe AWK n'empêchera que le champ 2. Dans les deux cas, j'ai ajouté un moyen de supprimer les espaces de début et de fin (pour une meilleure mise en forme).
#!/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')"
L'environnement { ... } | column -t -s "$(printf '%b' '\t')"
est de formater toute la table de manière jolie.
[.____] Veuillez noter que la fonction "$(printf '%b' '\t')"
pourrait être remplacée par $'\t'
Dans ksh, bash ou zsh.
Si vous avez le rs
(Reshape) utilitaire disponible, vous pouvez procéder comme suit:
rs -Tzc: < input.txt
Cela donne au format de sortie exactement comme spécifié dans la question, même aux largeurs de colonne dynamiques.
-T
Transpose les données d'entrée-z
tailles les colonnes de manière appropriée du maximum dans chaque colonne-c:
utilise le côlon comme séparateur de champ d'entréeCela fonctionne pour des tables de taille arbitraire, par exemple:
$ 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
$
rs
est disponible par défaut sur OS X (et probablement d'autres machines BSD). Il peut être installé sur Ubuntu (et la famille Debian) avec:
Sudo apt-get install rs
Edit : Extensible à n'importe quel nombre de lignes de sortie, dans une simple linger for
boucle:
for ((i=1;i<=2;i++)); do cut -d: -f "$i" input | paste -sd: ; done | column -t -s:
Réponse originale :
Vous pouvez le faire comme une doublure à utiliser bash
Substitution de processus:
paste -sd: <(cut -d: -f1 input) <(cut -d: -f2 input) | column -t -s:
Les -s
Option à paste
permet de gérer chaque fichier un à la fois. Les :
Délimiteur défini dans paste
est "capturé" par le -s
Option à column
à la fin, à la fin du format en faisant la mise en place des champs.
Les commandes cut
dans les deux substitutions de processus retirent le premier champ et le deuxième champ, respectivement.
S'il existe des lignes vierges dans l'entrée ou non, comme column -t -s:
va nettoyer la production indépendamment. (Il y avait des lignes vierges dans l'entrée d'origine spécifiée dans la question, mais elles ont été supprimées depuis la retraite. La commande ci-dessus fonctionne quelles que soient les lignes vides.)
Entrée - Contenu du fichier nommé "entrée" dans la commande ci-dessus:
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
Sortir:
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
En utilisant AWK, stockez la touche et la valeur et imprimez-les à la fin.
#!/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]
}
Le juste gérer awk -f ./script.awk ./input.txt
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
Avec gnu datamash
et column
de util-linux
:
datamash -t: transpose <infile | column -t -s:
Cela fonctionne avec plus de deux colonnes mais suppose qu'il n'y a pas de lignes vides dans votre fichier d'entrée; Avec des lignes vides entre les deux (comme dans votre exemple d'entrée initiale), vous obtiendrez une erreur comme:
datamash: transpose input error: line 2 has 0 fields (previous lines had 2);
afin d'éviter que vous ayez à les presser avant de traiter avec datamash
:
tr -s \\n <infile | datamash -t: transpose | column -t -s:
Sinon, dans ce cas particulier (seulement deux colonnes), avec zsh
et le même column
:
list=(${(f)"$(<infile)"})
printf %s\\n ${(j;:;)list[@]%:*} ${(j;:;)list[@]#*:} | column -t -s:
(${(f)"$(<infile)"})
lit les lignes dans un tableau; ${(j;:;)list[@]%:*}
joint (avec :
) Le premier champ de chaque élément et ${(j;:;)list[@]#*:}
joint (à nouveau avec :
) le deuxième champ de chaque élément; Celles-ci sont toutes deux imprimées, par ex. La sortie est
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
qui est ensuite pipi à column -t -s:
Utilisez datamash
et son option transpose
option pour échanger des lignes et des colonnes dans un fichier.
datamash -t: transpose < infile.txt
Par défaut, transpose vérifie l'entrée comporte le même nombre de champs dans chaque ligne et échoue avec une erreur sinon et vous pouvez désactiver son mode strict pour permettre aux valeurs manquantes de --no-strict
datamash -t: --no-strict transpose < infile.txt
Aussi, vous pouvez utiliser --filler
Pour définir la valeur de remplissage de champ manquant:
datamash -t: --no-strict --filler " " transpose < infile.txt
dérivé de datamash manual