Сравнение бок о бок с более чем двумя файлами, содержащими числовые значения

У меня есть три файла, содержащие отсортированную последовательность чисел, по одной в строке:

file1

1 2 3 

file2

 1 3 4 

file3

 1 5 

Я хочу «выровнять» эти три файла бок о бок, как показано ниже:

 file1 file2 file3 1 1 1 2 3 3 4 5 

Я пробовал с sdiff но он работает только с 2 файлами

  • Сравнение текстовых файлов с использованием Bash и AWK
  • Как найти файлы с тем же именем, но разные строки в двух каталогах?
  • diff -r только для определенных типов файлов
  • Понимание выходного сигнала
  • Разница между папками и файлами
  • Сохранение различий в двух файлах для модифицированных и новых дополнений
  • Сравнение двух файлов по горизонтали и по вертикали
  • Как сохранить изменения в моем vim-буфере в качестве файла патча?
  • 3 Solutions collect form web for “Сравнение бок о бок с более чем двумя файлами, содержащими числовые значения”

    Вы можете обрабатывать каждый файл и печатать строку с некоторым символом, например X для каждого недостающего числа в последовательности 1- max (где max – это последнее число в этом файле), paste результаты, затем заменить этот символ пробелом:

     paste \ <(awk 'BEGIN{n=1};{while (n<$1) {print "X";n++}};{n=$1+1};1' file1) \ <(awk 'BEGIN{n=1};{while (n<$1) {print "X";n++}};{n=$1+1};1' file2) \ <(awk 'BEGIN{n=1};{while (n<$1) {print "X";n++}};{n=$1+1};1' file3) \ | tr X ' ' 

    Если какое-то значение отсутствует во всех файлах, вы получите пустые строки в своем выходе (на самом деле они не пустые, они содержат только пробелы).
    Чтобы удалить их, замените tr X ' ' на sed '/[[:digit:]]/!d;s/X/ /g' Также, если вам нужен заголовок, вы всегда можете запустить что-то вроде этого:

      printf '\t%s' file1 file2 file3 | cut -c2- 

    Общее решение с awk: требует GNU awk

     gawk -v level=0 ' FNR==1 {level++; head[level]=FILENAME} !seen[$1]++ { n++; idx[$1] = n } { out[idx[$1]][level] = $1 } END { for (j=1; j<=level; j++) { printf "%s\t", head[j] } print "" for (i=1; i<=n; i++) { for (j=1; j<=level; j++) { printf "%s\t", out[i][j] } print "" } } ' file{1,2,3,4} 
     file1 file2 file3 file4 1 1 1 2 2 3 3 4 4 5 6 

    Взял другой и более простой подход к этому, основываясь на комментарии Дона:

     gawk ' FNR==1 { printf "%s\t", FILENAME } { seen[$1][FILENAME] = $1 } END { print "" PROCINFO["sorted_in"]="@ind_num_asc" for (i in seen) { for (j=1; j<=ARGC; j++) { printf "%s\t", seen[i][ARGV[j]] } print "" } } ' file{1,2,3,4} 
     file1 file2 file3 file4 1 1 2 3 3 4 4 5 5 6 7 

    Решение с bash , join , paste и bad taste:

     #! /usr/bin/env bash if [ $# -lt 3 ]; then exit 1; fi files=( '' "$@" ) declare -a temps for ((i=0; i<=$#; i++)); do [ $i -eq 0 -o -f "${files[$i]}" ] || exit 1 temps[$i]=$( mktemp -t "${0##*/}"_$$_XXXXXXXX ) || exit 1 done trap 'rm -f "${temps[@]}"' EXIT HUP INT QUIT TERM cat "$@" | sort -u >"${temps[0]}" TAB=$( printf '\t' ) for ((i=1; i<=$#; i++)); do join -j1 -a1 -t"$TAB" "${temps[0]}" <(paste "${files[$i]}" "${files[$i]}") | \ sed "/^[^$TAB]\$/ s/\$/$TAB/" >"${temps[$i]}" done printf '%s' ${files[1]} for ((i=2; i<=$#; i++)); do printf '\t%s' ${files[$i]} let j=i-1 let k=i-2 join -j1 -t"$TAB" "${temps[$j]}" "${temps[$i]}" >"${temps[$k]}" cat "${temps[$k]}" >"${temps[$i]}" done printf '\n' cut -d "$TAB" -f 2- <"${temps[$#]}" | sort -n 

    За исключением последнего sort -n , все это работает с любыми текстовыми элементами, а не с числами, если элементы не содержат вкладок (но TAB можно изменить на любой другой разделитель). Кроме того, это можно сделать только с тремя временными файлами и некоторыми перетасовками вокруг (но это только увеличит плохой вкус).

    Interesting Posts

    запустить pm2 из удаленного сценария оболочки

    Мастер-сценарий среды, основанный на $ LOGNAME для запуска любого вызова оболочки

    Перезапуск программы, работающей в фоновом режиме, и по-прежнему ее использовать из stdin

    Centos 6.5 использует только 24 ГБ / 48 ГБ памяти

    Бакула + летучая мышь на Ubuntu Maverick

    (Разрешено) Linux cdc_acm device – неожиданные символы, отправленные на USB-устройство

    Используйте определенный интерфейс для определенной подсети назначения (исходный IP-параметр)

    Как расширить среднюю файловую систему, используя только FDISK?

    btrfs error unknown – root fs не будет монтировать

    LUKS discard / TRIM: конфликтующие параметры командной строки ядра

    Установка qemu-user-static и binfmt-поддержки внутри LXC

    Поиск файлов и отображение их владельца

    Установка PostgreSQL 9.0 на RHEL 6.4 (Как заставить Yum включить версию OpenSSL, которую я построил из исходного кода)

    Я попадаю в состояние гонки в bash?

    Обновление емкости SSD – клонов

    Linux и Unix - лучшая ОС в мире.