Как можно отображать два несортированных текстовых файла разной длины рядом (в столбцах) в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
но наверняка команда для этого уже существует (или потенциально более чистое решение)?
linux
shell
unix
command-line
gnu-coreutils
Крис Сеймур
источник
источник
Ответы:
Вы можете использовать
pr
для этого-m
флаг, чтобы объединить файлы, по одному на столбец, и-t
опустить заголовки, например.выходы:
Смотрите также:
источник
pr
чем раньше не слышал . Я пробовал с 3 файлами, и вывод был усечен, но-w
вариант решил это. Хороший ответ.$COLUMNS
, который должен быть предоставлен оболочкой.pr
обрезает конец длинных строк. Есть ли способ заставить его обернуть строки?Чтобы немного расширить ответ @Hasturkun : по умолчанию
pr
для вывода используется только 72 столбца, но относительно легко заставить его использовать все доступные столбцы окна вашего терминала:pr -w $COLUMNS -m -t one.txt two.txt
Большинство командных интерпретаторов сохранят (и обновят) ширину экрана вашего терминала в
$COLUMNS
переменной окружения, поэтому мы просто передаем это значение,pr
чтобы использовать его для настройки ширины вывода.Это также отвечает на вопрос @Matt :
Итак, нет:
pr
сам по себе не может определить ширину экрана, но мы немного помогаем, передав ширину терминала через-w
опцию.источник
Если вы знаете , что входные файлы не имеют вкладок, а затем с помощью
expand
Упрощает @oyss «S ответа :Если во входных файлах могут быть вкладки, вы всегда можете сначала развернуть:
источник
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])} }'
Использование
*
в спецификации формата позволяет динамически указывать длину поля.источник
diff -y one.txt two.txt
будет лучше, чемpaste one.txt two.txt
удаление лишних символов различий, которые отображаются сsed
, тривиально по сравнению с написанием / запоминаниемawk
скрипта. Даже с обеими функциями.bash_rc
дольше! = Лучше, читабельнее, быстрее .. в чем преимущество?удаление динамического подсчета длины поля из ответа Бармара сделает его намного короче .... но вам все равно нужен хотя бы один скрипт для завершения работы, чего нельзя было избежать независимо от того, какой метод вы выберете.
paste one.txt two.txt |awk -F'\t' '{printf("%-50s %s\n",$1,$2)}'
источник
Если вы хотите узнать реальную разницу между двумя файлами, расположенными рядом, используйте
diff -y
:Вы также можете установить ширину вывода, используя
-W, --width=NUM
опцию:и чтобы
diff
вывод столбца соответствовал вашему текущему окну терминала:diff -y -W $COLUMNS file1.cf file2.cf
источник
Есть
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"
отобразит:
источник
Найдите ниже решение на основе 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]
пример
источник
diff -y <file1> <file2> [root /]# cat /one.txt
[root /]# cat /two.txt
[root@RHEL6-64 /]# diff -y one.txt two.txt
источник
sdiff
вdiff -y
котором я обсуждаю в этом вопросе.diff
добавляет символы между двумя файлами.