Comment peut-on afficher côte à côte deux fichiers texte non triés de longueurs différentes (en colonnes) dans un Shell
name__
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 sdiff
name__, puis conduit à sed pour supprimer la sortie sdiff
name__, 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)?
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
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
.
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.
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
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)}'
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 !:
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
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
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