Как объединить файлы с разделителями табуляции?

У меня есть 3 файла с разделителями табуляции, как показано ниже:

Файл 1:

1   Hhe.7
2   Hpyl.1
10  Hac.2

Файл 2:

3   Hac.2
15  Hpyl.1
33  Hhe.7

Файл 3:

70  Hpyl.1
23  Hhe.7
9   Hac.2

Как объединить эти файлы (используя командную строку) в один файл, чтобы получить следующий вывод:

1  33  23  Hhe.7
2  15  70  Hpyl.1
10  3  9  Hac.2
3
задан 12 April 2016 в 14:11

5 ответов

В маленьком сценарии Python можно объединить неограниченное количество файлов:

#!/usr/bin/env python3
import sys

#read the files, split the lines for reordering
lines = sum([[l.strip().split() for l in open(f).readlines()]\
             for f in sys.argv[1:]], [])
# get the unique last sections
values = set(map(lambda x:x[1], lines))
# combine them with the combined first sections
newlist = [[y[0] for y in lines if y[1]==x]+[x] for x in values]
for l in newlist:
    print(("\t").join(l))

Скопируйте его в пустой файл, сохраните его как merge.py, выполните его командой:

python3 /path/to/merge.py file1, file2, file3 (file4, file5 etc.)

Вывод на Ваших файлах в качестве примера:

10  3   9   Hac.2
1   33  23  Hhe.7
2   15  70  Hpyl.1

Добавление большего количества файлов

Как упомянуто, количество файлов в принципе неограниченно, если я добавляю 4-й файл:

40   Hhe.7
50   Hpyl.1
60   Hac.2

и выполненный команда:

python3 /path/to/merge.py file1, file2, file3, file4

вывод будет:

40  23  33  1   Hhe.7
50  70  15  2   Hpyl.1
60  9   3   10  Hac.2
1
ответ дан 13 April 2016 в 00:11
  • 1
    Didn' t работа: (перезагруженная и сенсорная панель все еще wasn' t обнаруженный. Была ошибка в выводе, что-то версия модуля для psmouse.ko быть более новым, чем, что найдено в ядре – jod 23 August 2017 в 03:26

Классический инструмент UNIX для этого join:

NAME
       join - join lines of two files on a common field

SYNOPSIS
       join [OPTION]... FILE1 FILE2

DESCRIPTION
       For  each  pair of input lines with identical join fields, write a line
       to standard output.  The default join field is the first, delimited  by
       blanks.

Однако join i) нуждается в его входе, который будет отсортирован, для работы и ii) может только иметь дело с 2 файлами. Так, Вы могли сделать что-то ужасное и неэлегантное как:

  1. Вид каждый файл на втором поле и сохраняет как новый файл

    sort -k2 file1 > sorted1
    sort -k2 file2 > sorted2
    sort -k2 file3 > sorted3
    
  2. Файлы 1 и 2 соединения в новый файл и затем присоединяются к третьему

    $ join -j2 --nocheck-order sorted1 sorted2 > newfile
    $ join -o 1.2,1.3,2.1,1.1  -1 1 -2 2 --nocheck-order newfile sorted3 
    10 3 9 Hac.2
    1 33 23 Hhe.7
    2 15 70 Hpyl.1
    

    Используемые опции:

       -1 FIELD
              join on this FIELD of file 1
    
       -2 FIELD
              join on this FIELD of file 2
       -j FIELD
              equivalent to '-1 FIELD -2 FIELD'
    
       --nocheck-order
              do not check that the input is correctly sorted
    
       -o FORMAT
              obey FORMAT while constructing output line
       FORMAT is one or more  comma  or  blank  separated
       specifications, each being 'FILENUM.FIELD' or '0'. 
    

    Так, та команда присоединится на 1-м поле первого файла и 2-м поле второго файла, и распечатает 2-е поле первого файла (1.2), затем третье поле первого файла (1.3), первое поле второго файла (2.1) и 1-е поле первого файла (1.1).

С другой стороны, Вы могли объединить всю вещь в одной великолепно сложной команде:

$ join -o 1.1,2.2,2.3,2.1 -1 2 -2 1  --nocheck-order <(sort -k2 file3) \
      <(join -j2  --nocheck-order <(sort -k2 file1) <(sort -k2 file2)) 
9 10 3 Hac.2
23 1 33 Hhe.7
70 2 15 Hpyl.1

Если Вам не нравится тайная командная-строка-fu, можно всегда использовать немного сценария:

$ awk '{a[$NF]=$1"\t"a[$NF];} END{for(i in a){print a[i],i}}' file{1,2,3} 
23  33  1    Hhe.7
9   3   10   Hac.2
70  15  2    Hpyl.1
4
ответ дан 12 April 2016 в 14:11

Это - задание для join, который может присоединиться на общих полях двух файлов:

$ join -11 -22 -o1.2,1.3,2.1,0 <(join -j2 <(sort -k2,2 f1.txt) <(sort -k2,2 f2.txt)) <(sort -k2,2 f3.txt)
10 3 9 Hac.2
1 33 23 Hhe.7
2 15 70 Hpyl.1

Как join берет только два входных файла за один раз, мы использовали замену процесса (<()) для передачи вывода join - луг сначала два файла с третьим.

3
ответ дан 13 April 2016 в 00:11
  • 1
    Я действительно отключал безопасную начальную загрузку для установки. Я отключу его и попробую еще раз. – jod 23 August 2017 в 04:11

С awk:

awk -F"\t" -v OFS="\t" '!(a[$2]){a[$2]=$1;next}
{a[$2]=a[$2]"\t"$1} 
END{
for ( i in a) {
    print a[i],i
    }
}'
1
ответ дан 13 April 2016 в 00:11
  • 1
    Если существует какая-либо ошибка, отправьте ее на свой вопрос. Возможно, версия должна быть изменена. – Pilot6 23 August 2017 в 04:12

Ответ от:

Следующий сценарий должен сделать, внешнее объединение на столбце (поле) 1 всех файлов с разделением табуляцией передало как аргументы. Это использует команду соединения, которая делает внешнее объединение на отсортированных файлах, 2 файла за один раз.

Это присоединится к каждой строке в файлах, включая строки заголовка. Если Вы хотите, чтобы заголовки были исключены, изменили два sort команды к чему-то, что производит отсортированный файл, который опускает их.

#!/bin/sh
if test $# -lt 2
then
    echo usage: gjoin file1 file2 ...
    exit 1
fi
sort -t $'\t' -k 1 "$1" > result
shift
for f in "$@"
do
    sort -t $'\t' -k 1 "$f" > temp
    join -1 1 -2 1 -t $'\t' result temp > newresult
    mv newresult result
done
cat result
rm result temp

Если у Вас есть более старая оболочка, $'\t' не будет заменен вкладкой, таким образом, необходимо будет использовать 'ВКЛАДКУ', куда Вы помещаете литеральную вкладку между кавычками.

Оптимизация возможна если, вместо /bin/sh, можно использовать современную оболочку, такую как удар или ksh; например, строки

sort -t $'\t' -k 1 "$f" > temp
join -1 1 -2 1 -t $'\t' result temp > newresult

может быть заменен

join -1 1 -2 1 -t $'\t' result <(sort -t $'\t' -k 1 "$f") > newresult
0
ответ дан 13 April 2016 в 00:11
  • 1
    вывод dpkg, отправленный выше. я должен использовать - сила, и раз так который является опцией к dpkg? – jod 23 August 2017 в 04:14

Другие вопросы по тегам:

Похожие вопросы: