web-dev-qa-db-fra.com

Comment imprimer des valeurs dans un fichier texte en fichier colonne à l'aide du script Shell

J'ai un fichier output.txt associé à l'exécution d'un script Shell, comme suit:

abc.txt
errorstatus1
Fri Nov 11 02:00:09 2016
def.txt
errorstatus2.txt
Sat Nov 12 03:00:09 2016

Le fichier texte a plusieurs entrées ligne par ligne de la même manière. Je veux imprimer ces valeurs dans les colonnes: Nom du fichier, Statut et Horodatage comme suit:

Filename      Status        Timestamp
abc.txt     errorstatus1   Fri Nov 11 02:00:09 2016
def.txt     errorstatus2   Sat Nov 12 03:00:09 2016
11
linux09

Avec pastename__:

paste - - - <file.txt

cela produira le contenu du fichier séparé par une nouvelle ligne sous forme de colonnes et trois colonnes séparées par des tabulations par ligne.

Ajout de l'en-tête:

echo Filename Status Timestamp; paste - - - <file.txt

Pour classer la sortie, utilisez l’aide de columnname__:

{ echo Filename Status Timestamp; paste - - - <file.txt ;} | column -t

Exemple:

% cat file.txt
abc.txt
errorstatus1
Fri Nov 11 02:00:09 2016
def.txt
errorstatus2.txt
Sat Nov 12 03:00:09 2016

% { echo Filename Status Timestamp; paste - - - <file.txt ;} | column -t
Filename  Status            Timestamp
abc.txt   errorstatus1      Fri        Nov  11  02:00:09  2016
def.txt   errorstatus2.txt  Sat        Nov  12  03:00:09  2016
14
heemayl

Vous pouvez utiliser awk:

awk 'NR % 3 {printf "%s ", $0; next}1'

La sortie pourrait ne pas être aussi jolie:

$ awk 'NR % 3 {printf "%s ", $0; next} 1' input
abc.txt errorstatus1 Fri Nov 11 02:00:09 2016
def.txt errorstatus2.txt Sat Nov 12 03:00:09 2016

Vous pouvez utiliser %s\t à la place pour une sortie séparée par des tabulations.

  • NR % 3 vaut zéro (et faux) pour chaque troisième ligne. Les autres lignes sont donc imprimées avec un espace après celles-ci au lieu d'une nouvelle ligne. next commence juste la prochaine itération.
  • Chaque troisième ligne est imprimée telle quelle à cause du 1 final, suivi d'une nouvelle ligne, car il ne correspond pas au premier bloc.
6
muru

Il y a aussi rs (BSD r e s utilitaire hape):

DESCRIPTION
     rs reads the standard input, interpreting each line as a row of blank-
     separated entries in an array, transforms the array according to the
     options, and writes it on the standard output.  With no arguments it
     transforms stream input into a columnar format convenient for terminal
     viewing.

En particulier,

     -e      Consider each line of input as an array entry.

Alors

$ rs -e < file
abc.txt                   errorstatus1              Fri Nov 11 02:00:09 2016
def.txt                   errorstatus2.txt          Sat Nov 12 03:00:09 2016

ou (pour ajouter l'en-tête)

$ { printf '%s\n' Filename Status Timestamp ; cat file ; } | rs -e
Filename                  Status                    Timestamp
abc.txt                   errorstatus1              Fri Nov 11 02:00:09 2016
def.txt                   errorstatus2.txt          Sat Nov 12 03:00:09 2016
5
steeldriver

Pour être complet, vous pouvez également le faire avec sed:

sed -e '1iFilename\tStatus\tTimestamp' -e 'N;N;y/\n/\t/' file.txt
  • 1iFilename\tStatus\tTimestamp insère la ligne d'en-tête avant la ligne 1
  • N;N lit deux autres lignes dans le tampon de modèle, pour un total de 3 lignes séparées par une nouvelle ligne
  • y/\n/\t/ remplace toutes les nouvelles lignes par des onglets dans le tampon de modèle

Les commandes i, N et y sed sont documentées ici .

3
Digital Trauma

Il est toujours possible de préparer quelque chose pour le traitement de texte avec AWK ou Perl, et bien sûr en Python, ce que cette réponse fournit.

En une ligne:

python -c 'import sys;print "Filename\tStatus\tTimestamp"; lines=[l.strip() for l in sys.stdin];print "".join([l+"\n" if i%3 == 0 else l+"\t" for i,l in enumerate(lines,1) ])' < input.txt

Comme script multi-lignes

import sys
print "Filename\tStatus\tTimestamp"
lines=[l.strip() for l in sys.stdin]
print "".join([l+"\n" if i%3 == 0 else l+"\t" for i,l in enumerate(lines,1) ])

L'idée de base est de donner l'entrée de script via stdin (en utilisant la redirection de Shell <, bien qu'un canal puisse aussi être utilisé). Le script utilise des tabulations pour séparer les champs, bien que des espaces puissent également être utilisés pour une sortie plus "affinée".

Exemple de sortie utilisant l'exemple d'entrée fourni par OP:

$ python -c 'import sys;print "Filename\tStatus\tTimestamp";                                   
> lines=[l.strip() for l in sys.stdin];
> print "".join([l+"\n" if i%3 == 0 else l+"\t" for i,l in enumerate(lines,1) ])' < input.txt
Filename    Status  Timestamp
abc.txt errorstatus1    Fri Nov 11 02:00:09 2016
def.txt errorstatus2    Sat Nov 12 03:00:09 2016
1
Sergiy Kolodyazhnyy