Отображение двух файлов рядом

95

Как можно отображать два несортированных текстовых файла разной длины рядом (в столбцах) вshell

Учитывая one.txtи 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

Дисплей:

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почти выполняет трюк, но не выравнивает столбцы должным образом, поскольку он просто печатает одну вкладку между столбцами 1 и 2. Я знаю, как это сделать с помощью emacs и vim, но хочу, чтобы вывод отображался в stdout для трубопроводов и т. д.

Решение, которое я придумал, использует, sdiffа затем каналы для sed, чтобы удалить sdiffдобавленные выходные данные .

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

Я мог бы создать функцию и вставить ее в свою, .bashrcно наверняка команда для этого уже существует (или потенциально более чистое решение)?

Крис Сеймур
источник
Не в оболочке, но стоит упомянуть: используйте meld !
fedorqui 'SO stop harming'

Ответы:

167

Вы можете использовать prдля этого -mфлаг, чтобы объединить файлы, по одному на столбец, и -tопустить заголовки, например.

pr -m -t one.txt two.txt

выходы:

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

                                    skipped a line

Смотрите также:

Хастуркун
источник
15
Отлично! Знал, что что-то будет существовать, о prчем раньше не слышал . Я пробовал с 3 файлами, и вывод был усечен, но -wвариант решил это. Хороший ответ.
Крис Сеймур
5
@sudo_o: Рад помочь, coreutils полон драгоценных камней
Hasturkun
1
Есть ли способ для автоматического определения ширины экрана?
Мэтт
2
@Matt: вы можете использовать $COLUMNS, который должен быть предоставлен оболочкой.
Hasturkun
1
При использовании для печати двух файлов бок о бок prобрезает конец длинных строк. Есть ли способ заставить его обернуть строки?
molnarg 08
32

Чтобы немного расширить ответ @Hasturkun : по умолчанию prдля вывода используется только 72 столбца, но относительно легко заставить его использовать все доступные столбцы окна вашего терминала:

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

Большинство командных интерпретаторов сохранят (и обновят) ширину экрана вашего терминала в $COLUMNSпеременной окружения, поэтому мы просто передаем это значение, prчтобы использовать его для настройки ширины вывода.

Это также отвечает на вопрос @Matt :

Есть ли способ для автоматического определения ширины экрана?

Итак, нет: prсам по себе не может определить ширину экрана, но мы немного помогаем, передав ширину терминала через -wопцию.

пванденберк
источник
7

Если вы знаете , что входные файлы не имеют вкладок, а затем с помощью expandУпрощает @oyss «S ответа :

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

Если во входных файлах могут быть вкладки, вы всегда можете сначала развернуть:

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

Использование *в спецификации формата позволяет динамически указывать длину поля.

Barmar
источник
1
Никогда не говорил, что это так, но если я хочу иногда отображать два файла бок о бок, то выполнение этой работы diff -y one.txt two.txtбудет лучше, чем paste one.txt two.txtудаление лишних символов различий, которые отображаются с sed, тривиально по сравнению с написанием / запоминанием awkскрипта. Даже с обеими функциями .bash_rcдольше! = Лучше, читабельнее, быстрее .. в чем преимущество?
Крис Сеймур,
2

удаление динамического подсчета длины поля из ответа Бармара сделает его намного короче .... но вам все равно нужен хотя бы один скрипт для завершения работы, чего нельзя было избежать независимо от того, какой метод вы выберете.

paste one.txt two.txt |awk -F'\t' '{printf("%-50s %s\n",$1,$2)}'
ойсс
источник
2

Если вы хотите узнать реальную разницу между двумя файлами, расположенными рядом, используйте diff -y:

diff -y file1.cf file2.cf

Вы также можете установить ширину вывода, используя -W, --width=NUMопцию:

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

и чтобы diffвывод столбца соответствовал вашему текущему окну терминала:

diff -y -W $COLUMNS file1.cf file2.cf
пользователь3498040
источник
2

Есть 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 /;
    "

Под , вы можете использовать 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 /;"

(Из решения конечно @Hasturkun «s prявляется наиболее точным !) :

Преимущество sedболееpr

Вы можете точно выбрать ширину разделения и / или разделители:

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

Или, для примера, отметить строки, содержащие 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"

отобразит:

apple                         |  | The quick brown fox..
pear                          |  | foo
longer line than the last two |ln| bar 
last line                     |ln| linux
                              |  | 
                              |ln| skipped a line
Ф. Хаури
источник
1

Найдите ниже решение на основе 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]

пример

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
яблоко
груша
длиннее двух последних
Последняя линия
[root /]# cat /two.txt
Быстрая коричневая лиса ..
фу
бар
linux
[root@RHEL6-64 /]# diff -y one.txt two.txt
яблоко | Быстрая коричневая лисица ..
груша | фу
длиннее двух последних | бар
последняя строка | linux
iAdhyan
источник
sdiffв diff -yкотором я обсуждаю в этом вопросе.
Крис Сеймур
Да, верно ... было упомянуто, чтобы показать другую настройку команды / флага для этого.
iAdhyan 02
Но он не отвечает на вопросы, diffдобавляет символы между двумя файлами.
Крис Сеймур