Afficher deux fichiers côte à côte
Comment 2 fichiers texte non triés de différentes longueurs peuvent-ils être affichés côte à côte (en colonnes) dans un shell
Donnée 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
Affichage:
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'a pas bien aligné les colonnes car il imprime juste un onglet entre les colonnes 1 et 2. Je sais comment faire avec emacs et vim mais je veux que la sortie soit affichée sur stdout pour la tuyauterie ect.
La solution que j'ai trouvée utilise sdiff
puis des tuyaux pour sed pour supprimer la sortie sdiff
ajoute.
sdiff one.txt two.txt | sed -r 's/[<>|]//;s/(t){3}//'
Je pourrais créer une fonction et le coller dans mon .bashrc
, mais sûrement une commande pour cela existe déjà (ou un nettoyant solution potentiellement)?
9 réponses
Vous pouvez utiliser pr
pour ce faire, 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
Sorties:
apple The quick brown fox..
pear foo
longer line than the last two bar
last line linux
skipped a line
Pour développer un peu la réponse de @Hasturkun: par défaut, pr
n'utilise que 72 colonnes pour sa sortie, mais il est relativement facile de le faire utiliser toutes les colonnes disponibles de votre fenêtre de 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
, donc nous passons simplement cette valeur à pr
pour l'utiliser pour le paramètre de largeur de sortie.
Cela répond également à la question de @Matt:
Est là une façon pour pr de détecter automatiquement la largeur de l'écran?
Donc, non: pr
lui-même ne peut pas détecter la largeur d'écran, mais nous aidons un peu en passant dans la largeur du terminal via l'option -w
.
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])}
}'
L'utilisation de *
dans une spécification de format vous permet de fournir la longueur du champ dynamiquement.
Si vous connaissez les fichiers d'entrée ont pas d'onglets, puis à l'aide de expand
simplifie @oyss's réponse:
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
Supprimer dynamiquement le comptage de longueur de champ de la réponse de Barmar en fera une commande beaucoup plus courte....mais vous avez encore besoin d'au moins un script pour terminer le travail qui ne pouvait être évitée peu importe la méthode que vous choisissez.
paste one.txt two.txt |awk -F'\t' '{printf("%-50s %s\n",$1,$2)}'
Il y a un moyen 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 sûr, la solution de @ Hasturkun pr
est la la plus précise!):
Si vous voulez connaître la différence réelle entre deux fichiers, utilisez la commande ci-dessous
diff -y file1.cf file2.cf
Vous pouvez également définir la largeur pour imprimer les colonnes à l'aide de l'option -W, --width=NUM
:
diff -y -W 150 file1.cf file2.cf
diff -y <file1> <file2>
[root /]# cat /one.txt
apple pear longer line than the last two last line
[root /]# cat /two.txt
The quick brown fox.. foo bar linux
[root@RHEL6-64 /]# diff -y one.txt two.txt
apple | The quick brown fox.. pear | foo longer line than the last two | bar last line | linux
Trouvez 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