Tampilkan dua file berdampingan

94

Bagaimana 2 file teks yang tidak diurutkan dengan panjang yang berbeda dapat ditampilkan berdampingan (dalam kolom) di ashell

Diberikan one.txtdan 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

Tampilan:

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

                                    skipped a line

paste one.txt two.txthampir melakukan trik tetapi tidak menyelaraskan kolom dengan baik karena hanya mencetak satu tab antara kolom 1 dan 2. Saya tahu bagaimana melakukannya dengan emacs dan vim tetapi ingin output ditampilkan ke stdout untuk perpipaan dll.

Solusi yang saya dapatkan dengan menggunakan sdiffdan kemudian menyalurkan ke sed untuk menghapus sdiffpenambahan keluaran .

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

Saya dapat membuat fungsi dan menempelkannya di saya .bashrctetapi pasti perintah untuk ini sudah ada (atau solusi yang lebih bersih berpotensi)?

Chris Seymour
sumber
Tidak dalam sebuah shell, tapi patut disebutkan: gunakan gabungan !
fedorqui 'JADI berhenti merugikan'

Jawaban:

166

Anda dapat menggunakan pruntuk melakukan ini, menggunakan -mbendera untuk menggabungkan file, satu per kolom, dan -tuntuk menghilangkan header, misalnya.

pr -m -t one.txt two.txt

keluaran:

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

                                    skipped a line

Lihat juga:

Hasturkun
sumber
15
Sempurna! Tahu sesuatu akan ada, tidak pernah terdengar prsebelumnya. Saya mencoba dengan 3 file dan hasilnya terpotong tetapi -wopsi menyelesaikannya. Jawaban bagus.
Chris Seymour
5
@sudo_o: Senang membantu, coreutils penuh dengan permata
Hasturkun
1
Apakah ada cara untuk mendeteksi lebar layar secara otomatis?
Matt
2
@Matt: Anda bisa menggunakan $COLUMNS, yang seharusnya disediakan oleh shell.
Hasturkun
1
Saat digunakan untuk mencetak dua file berdampingan, prmemotong ujung garis panjang. Apakah ada cara untuk membuatnya membungkus garis?
molnarg
32

Untuk sedikit memperluas jawaban @Hasturkun : secara default prhanya menggunakan 72 kolom untuk keluarannya, tetapi relatif mudah untuk membuatnya menggunakan semua kolom yang tersedia di jendela terminal Anda:

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

Sebagian besar shell akan menyimpan (dan memperbarui) layar lebar terminal Anda di $COLUMNSvariabel lingkungan, jadi kami hanya meneruskan nilai itu kepr untuk digunakan untuk pengaturan lebar keluarannya.

Ini juga menjawab pertanyaan @Matt :

Adakah cara bagi pr untuk mendeteksi lebar layar secara otomatis?

Jadi, no: prsendiri tidak dapat mendeteksi lebar layar, tetapi kami membantu sedikit dengan mengirimkan lebar terminal melalui -wopsi.

pvandenberk.dll
sumber
7

Jika Anda tahu input file tidak memiliki tab, kemudian menggunakan expandmenyederhanakan @oyss 's jawabannya :

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

Jika mungkin ada tab di file masukan, Anda selalu dapat meluaskan terlebih dahulu:

paste <(expand one.txt) <(expand two.txt) | expand --tabs=50
Bob
sumber
6
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])}
}'

Menggunakan *dalam spesifikasi format memungkinkan Anda menyediakan panjang bidang secara dinamis.

Barmar
sumber
1
Tidak pernah mengatakannya, tetapi jika saya ingin menampilkan dua file secara berdampingan sesekali maka melakukan diff -y one.txt two.txtpekerjaan yang lebih baik daripada paste one.txt two.txtdan menghapus karakter tambahan diffs yang ditampilkan dengan sedsepele dibandingkan dengan menulis / mengingat awkskrip. Bahkan dengan keduanya sebagai fungsi .bash_rclebih lama! = Lebih baik, lebih mudah dibaca, lebih cepat .. apa keuntungannya di sini?
Chris Seymour
2

menghapus secara dinamis panjang bidang yang dihitung dari jawaban Barmar akan membuatnya menjadi perintah yang jauh lebih pendek .... tetapi Anda masih memerlukan setidaknya satu skrip untuk menyelesaikan pekerjaan yang tidak dapat dihindari apa pun metode yang Anda pilih.

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

Jika Anda ingin mengetahui perbedaan sebenarnya antara dua file secara berdampingan, gunakan diff -y:

diff -y file1.cf file2.cf

Anda juga dapat mengatur lebar keluaran menggunakan -W, --width=NUMopsi:

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

dan untuk membuat diffkeluaran kolom sesuai dengan jendela terminal Anda saat ini:

diff -y -W $COLUMNS file1.cf file2.cf
pengguna3498040
sumber
2

Ada sedcaranya:

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

Dibawah , Anda bisa menggunakan printf -v:

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

(Tentu saja solusi @Hasturkun pradalah yang paling akurat !) :

Keuntungan sedlebihpr

Anda dapat memilih lebar pemisah dan atau pemisah dengan cermat:

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

Atau, sebagai contoh, untuk menandai garis yang mengandung line:

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

akan membuat:

apple                         |  | The quick brown fox..
pear                          |  | foo
longer line than the last two |ln| bar 
last line                     |ln| linux
                              |  | 
                              |ln| skipped a line
F. Hauri
sumber
1

Temukan di bawah solusi berbasis 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]

Contoh

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

                                 skipped a line
pengecut
sumber
0
diff -y <file1> <file2>


[root /]# cat /one.txt
apel
pir
garis yang lebih panjang dari dua yang terakhir
baris terakhir
[root /]# cat /two.txt
Rubah cokelat cepat ..
foo
batang
linux
[root@RHEL6-64 /]# diff -y one.txt two.txt
apel | Rubah cokelat cepat ..
pir | foo
garis yang lebih panjang dari dua | terakhir batang
baris terakhir | linux
iAdhyan
sumber
sdiffadalah diff -yyang saya bahas dalam pertanyaan.
Chris Seymour
Ya benar ... itu disebutkan untuk menunjukkan pengaturan perintah / bendera lain untuk melakukannya.
iAdhyan
Tapi itu tidak menjawab pertanyaan diffmenambahkan karakter di antara kedua file tersebut.
Chris Seymour