İki dosyayı yan yana görüntüleyin


95

Farklı uzunluklarda 2 sıralanmamış metin dosyası nasıl yan yana (sütunlar halinde) birshell

Verilen one.txtve 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

Görüntüle:

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

                                    skipped a line

paste one.txt two.txtneredeyse hile yapar, ancak sütun 1 ve 2 arasında sadece bir sekme yazdırdığı için sütunları güzelce hizalamaz. Bunu emacs ve vim ile nasıl yapacağımı biliyorum, ancak görüntülenen çıktının borulama vb. için stdout olmasını istiyorum.

Bulduğum çözüm kullanımları sdiffve daha sonra çıktının eklenmesini kaldırmak için sed için borular sdiff.

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

Bir işlev oluşturabilir ve bunu kendime yapıştırabilirim .bashrcama kesinlikle bunun için zaten bir komut var mı (veya potansiyel olarak daha temiz bir çözüm)?


Bir kabukta değil, ama bahsetmeye değer: meld kullanın !
fedorqui

Yanıtlar:


169

Bunu, her sütun için bir tane olmak üzere dosyaları birleştirmek priçin -mbayrağı kullanarak ve -tbaşlıkları atlamak için kullanabilirsiniz, örn.

pr -m -t one.txt two.txt

çıktılar:

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

                                    skipped a line

Ayrıca bakınız:


15
Mükemmel! Bir şeyin olacağını biliyordu, daha prönce hiç duymadım . 3 dosya ile denedim ve çıktı kesildi ama -wseçenek bunu çözdü. Güzel cevap.
Chris Seymour

5
@sudo_o: Yardımcı olmaktan mutluluk duyuyorum,
çekirdek

1
Pr'nin ekran genişliğini otomatik olarak algılamanın bir yolu var mı?
Matt

2
@Matt: $COLUMNSKabuk tarafından sağlanması gereken kullanabilirsiniz .
Hasturkun

1
İki dosyayı yan yana yazdırmak için kullanıldığında pr, uzun çizgilerin sonlarını keser. Çizgileri sarmanın bir yolu var mı?
molnarg

32

@Hasturkun'un cevabını biraz genişletmek için : varsayılan olarak prçıktısı için yalnızca 72 sütun kullanır, ancak terminal pencerenizin mevcut tüm sütunlarını kullanması nispeten kolaydır:

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

Çoğu kabuk , terminalinizin ekran genişliğini ortam değişkeninde depolayacak (ve güncelleyecektir)$COLUMNS , bu nedenle bu değeri prçıktının genişlik ayarı için kullanmak üzere aktarıyoruz.

Bu aynı zamanda @ Matt'in sorusunu da yanıtlıyor :

Pr'nin ekran genişliğini otomatik olarak algılamanın bir yolu var mı?

Yani, hayır: prkendisi ekran genişliğini algılayamıyor, ancak -wseçenek aracılığıyla terminalin genişliğini geçerek biraz yardımcı oluyoruz .


7

Biliyorsanız girdi dosyaları sonra kullanarak, hiçbir sekmeler de expandkolaylaştırır @oyss 'ın cevabı :

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

Giriş dosyalarında sekmeler varsa, her zaman önce genişletebilirsiniz:

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

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])}
}'

*Bir format spesifikasyonunda kullanmak , alan uzunluğunu dinamik olarak sağlamanıza izin verir.


1
Olduğunu hiç söylemedim, ancak ara sıra iki dosyayı yan yana görüntülemek istersem, o zaman yapmaktan diff -y one.txt two.txtdaha iyi bir iş paste one.txt two.txtçıkarır ve görüntülenen fazladan karakterleri kaldırmak sedbir awkkomut dosyası yazmak / hatırlamakla karşılaştırıldığında önemsizdir . Her ikisi de işlev olarak .bash_rcdaha uzun! = Daha iyi, daha okunaklı, daha hızlı .. burada avantaj nedir?
Chris Seymour

2

Barmar'ın cevabından dinamik alan uzunluğunu saymak onu çok daha kısa bir komut haline getirecektir .... ancak hangi yöntemi seçerseniz seçin kaçınılamayan işi bitirmek için yine de en az bir betiğe ihtiyacınız var.

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

2

İki dosya arasındaki gerçek farkı yan yana bilmek istiyorsanız, şunu kullanın diff -y:

diff -y file1.cf file2.cf

Ayrıca şu -W, --width=NUMseçeneği kullanarak bir çıktı genişliği de ayarlayabilirsiniz :

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

ve diffsütun çıktısını mevcut terminal pencerenize sığdırmak için:

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

2

Bir sedyol var:

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

Altında şunları kullanabilirsiniz 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 /;"

(Ders @Hasturkun 'ın çözümü Of prolduğu en doğru !) :

Avantajı sedoverpr

Ayırma genişliğini ve / veya ayırıcılarını hassas bir şekilde seçebilirsiniz:

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 /;"

Veya numune için lineşunları içeren satırları işaretlemek için :

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"

render:

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

1

Aşağıda python tabanlı bir çözüm bulun.

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]

Misal

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

                                 skipped a line

0
diff -y <file1> <file2>


[root /]# cat /one.txt
elma
armut
son ikiden daha uzun çizgi
son satır
[root /]# cat /two.txt
Hızlı kahverengi tilki..
foo
bar
linux
[root@RHEL6-64 /]# diff -y one.txt two.txt
elma | Hızlı kahverengi tilki..
armut | foo
son ikiden daha uzun çizgi | bar
son satır | linux

sdiffolduğu diff -ySöz tartışmak hangi.
Chris Seymour

Evet doğru ... bunu yapmanın başka bir komut / bayrak ayarını göstermesinden bahsedildi.
Vikas Jain

Ancak soruları cevaplamaz diff, iki dosya arasına karakterler ekler.
Chris Seymour
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.