it-swarm.com.ru

Показать два файла рядом

Как можно отображать 2 несортированных текстовых файла различной длины рядом (в столбцах) в 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, но наверняка команда для этого уже существует (или потенциально - cleaner solution)?

78
Chris Seymour

Вы можете использовать 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

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

142
Hasturkun

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

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

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

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

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

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

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

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

6
Barmar

Если вы знаете, что во входных файлах нет вкладок, то использование expand упрощает @oyss 's answer :

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

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

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

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

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

Существует 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 /;
    "

(Конечно, решение @Hasturkun pr является наиболее точным !):

1
F. Hauri

Если вы хотите узнать реальную разницу между двумя файлами рядом, используйте 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
1
user3498040

Найдите ниже решение на основе 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
funk
diff -y <file1> <file2>


[root /]# cat /one.txt
 Apple 
 Pear 
 Длинная строка, чем последние два 
 Последняя строка 
[root /]# cat /two.txt
 Быстрая коричневая лиса ..
 Foo 
 Bar 
 Linux 
[[email protected] /]# diff -y one.txt two.txt
 Apple | Быстрая коричневая лиса ..
 Груша | foo 
 длиннее строки, чем последние два | бар 
 последняя строка | линукс 
0
iAdhyan