web-dev-qa-db-fra.com

Afficher deux fichiers côte à côte

Comment peut-on afficher côte à côte deux fichiers texte non triés de longueurs différentes (en colonnes) dans un Shellname__

one.txt et two.txt:

$ cat one.txt
Apple
pear
longer line than the last two
last line

$ cat two.txt
The quick brown fox..
foo
bar 
linux

skipped a line

Afficher:

Apple                               The quick brown fox..
pear                                foo
longer line than the last two       bar 
last line                           linux

                                    skipped a line

paste one.txt two.txt fait presque l'affaire mais n'aligne pas bien les colonnes car il ne fait qu'imprimer un seul onglet entre les colonnes 1 et 2. Je sais comment procéder avec emacs et vim, mais je souhaite que la sortie soit affichée sur stdout pour piping ect.

La solution que j'ai proposée utilise sdiffname__, puis conduit à sed pour supprimer la sortie sdiffname__, ajoute.

sdiff one.txt two.txt | sed -r 's/[<>|]//;s/(\t){3}//'

Je pourrais créer une fonction et la coller dans mon .bashrc mais sûrement une commande pour cela existe déjà (ou un cleaner solution potentiellement)?

78
Chris Seymour

Vous pouvez utiliser pr pour cela, en utilisant l'indicateur -m pour fusionner les fichiers, un par colonne, et -t pour omettre les en-têtes, par exemple.

pr -m -t one.txt two.txt

les sorties:

Apple                               The quick brown fox..
pear                                foo
longer line than the last two       bar
last line                           linux

                                    skipped a line

Voir également:

142
Hasturkun

Pour développer un peu la réponse de @Hasturkun : par défaut, pr utilise seulement 72 colonnes pour sa sortie, mais il est relativement facile de lui faire utiliser toutes les colonnes disponibles de la fenêtre de votre terminal:

pr -w $COLUMNS -m -t one.txt two.txt

La plupart des Shell vont stocker (et mettre à jour) la largeur d'écran de votre terminal dans la variable d'environnement $COLUMNS. Nous ne faisons donc que transmettre cette valeur à pr à utiliser pour le paramètre de largeur de sa sortie.

Ceci répond également à la question de @Matt :

Existe-t-il un moyen de détecter automatiquement la largeur de l'écran?

Donc, non: pr ne peut pas détecter la largeur de l'écran, mais nous aidons un peu en transmettant la largeur du terminal via l'option -w.

25
pvandenberk
paste one.txt two.txt | awk -F'\t' '{
    if (length($1)>max1) {max1=length($1)};
    col1[NR] = $1; col2[NR] = $2 }
    END {for (i = 1; i<=NR; i++) {printf ("%-*s     %s\n", max1, col1[i], col2[i])}
}'

Utiliser * dans une spécification de format vous permet de fournir la longueur du champ de manière dynamique.

6
Barmar

Si vous savez que les fichiers d'entrée n'ont pas de tabulation, alors utiliser expand simplifie @oyss 's answer :

paste one.txt two.txt | expand --tabs=50

S'il peut y avoir des onglets dans les fichiers d'entrée, vous pouvez toujours développer en premier:

paste <(expand one.txt) <(expand two.txt) | expand --tabs=50
5
Bob

supprimer dynamiquement le comptage de la longueur des champs de la réponse de Barmar en fera une commande beaucoup plus courte.

paste one.txt two.txt |awk -F'\t' '{printf("%-50s %s\n",$1,$2)}'
2
oyss

Il y a une manière sed:

f1width=$(wc -L <one.txt)
f1blank="$(printf "%${f1width}s" "")"
paste one.txt two.txt |
    sed "
        s/^\(.*\)\t/\1$f1blank\t/;
        s/^\(.\{$f1width\}\) *\t/\1 /;
    "

(Bien entendu, la solution de __Hasturkun pr est la la plus précise !:

1
F. Hauri

Si vous voulez connaître la différence réelle entre deux fichiers côte à côte, utilisez diff -y:

diff -y file1.cf file2.cf

Vous pouvez également définir une largeur de sortie à l'aide de l'option -W, --width=NUM:

diff -y -W 150 file1.cf file2.cf

et pour adapter la sortie de la colonne diff à la fenêtre de votre terminal actuel:

diff -y -W $COLUMNS file1.cf file2.cf
1
user3498040

Vous trouverez ci-dessous une solution basée sur Python.

import sys

# Specify the number of spaces between the columns
S = 4

# Read the first file
l0 = open( sys.argv[1] ).read().split('\n')

# Read the second file
l1 = open( sys.argv[2] ).read().split('\n')

# Find the length of the longest line of the first file
n = len(max(l0, key=len))

# Print the lines
for i in  xrange( max( len(l0), len(l1) ) ):

    try:
        print l0[i] + ' '*( n - len(l0[i]) + S) + l1[i]
    except:
        try:
            print ' ' + ' '*( n - 1 + S) + l1[i]
        except:
            print l0[i]

Exemple

Apple                            The quick brown fox..
pear                             foo
longer line than the last two    bar 
last line                        linux

                                 skipped a line
0
funk
diff -y <file1> <file2>


[root /]# cat /one.txt
 Apple 
 Pear 
 Ligne plus longue que les deux dernières 
 Dernière ligne 
[root /]# cat /two.txt
 Le renard brun rapide ..
 Foo 
 Bar 
 Linux 
[root@RHEL6-64 /]# diff -y one.txt two.txt
 Apple | Le renard brun rapide ..
 Poire | foo 
 ligne plus longue que les deux dernières | bar 
 dernière ligne | linux 
0
iAdhyan