объединить несколько файлов, используя общие IDS

  • CLUI :пользовательский интерфейс командной строки
  • GUI :графический интерфейс пользователя

Эти вещи означают то, что они означают, не более того.

Эти определения ничего не говорят о tty.Например, cmd.exe в Windows также является CLUI, хотя он не использует никаких tty-устройств (, он концептуально не существует в Windows ).

Tty означает средство записи консоли виртуального телетайпа, что является традиционным названием псевдовиртуальных терминалов в Unix-системах. По умолчанию (после загрузки )на них запускается консоль персонажа, но к ним можно подключить что угодно.

Лучше всего понимать tty, если рассматривать их как сетевые сокеты:Процессы могут прослушивать их, а также соединять их. Кроме того, существуют различные API-интерфейсы ядра для взаимодействия с пользователем :, например, если виртуальный терминал неожиданно закрывается, меняет свой размер, активируется или деактивируется, то подключенные к ним процессы получают разные сигналы . От них зависит, что они с этим сделают.

Например, X-сервер, работающий на tty7, если вы переключитесь на символьную консоль (alt/ctrl/f1 ), то он деинициализирует видеокарту и переключится обратно в символьный режим. Другие процессы, например командная оболочка, могут делать совсем другое.

1
02.01.2020, 16:03
3 ответа

Вероятно, это невозможно с помощью одного инструмента. Вот предложение на основе сценария -, которое включает вызов sortи два временных внешних файла.

#!/bin/bash

# The number of columns is equal to the number of input files, which is
# equal to the number of command-line arguments.
NUMCOLS=$#


# Use associative container to record all "IDs" and associated fields
declare -A entries
col=0


# Read the fields from all files and store them so that the field values can be
# associated with the file they came from (= the column they belong).
for FILE in "$@"
do
    while read id value
    do
        SORTKEY="$id"__"$col"
        entries[$SORTKEY]="$value"
        echo "$id" >> "tmp.ids"
    done < $FILE
    let col=$col+1
done

# Sort the IDs
sort -u "tmp.ids" > "tmp.ids.sorted"


# Read the sorted IDs back in and generate output lines, where the
# column fields are taken from the associative container "entries" and
# tab-separated.
# If "entries" doesn't contain a value for a given key, output "-NA-" instead.

while read id
do
    LINE="$id"
    for (( col=0; col<NUMCOLS; col++ ))
    do
        SORTKEY="$id"__"$col"
        if [[ -z "${entries[$SORTKEY]}" ]]
        then
            LINE=$(printf "%s\t-NA-" "$LINE")
        else
            LINE=$(printf "%s\t%s" "$LINE" "${entries[$SORTKEY]}")
        fi
    done
    echo "$LINE" >> "outfile.txt"
done < "tmp.ids.sorted"

rm tmp.ids tmp.ids.sorted

Вы бы назвали это как ./sortscript.sh <file1> <file2>... <fileN>.

Это создаст ассоциативный контейнер entriesи сохранит все поля, считанные из ваших входных файлов, под ключом, сгенерированным из поля «ID» и номера столбца. Идентификаторы записываются во внешний файл tmp.ids, чтобы их можно было отсортировать, что, похоже, вам и нужно.

После сортировки идентификаторы считываются обратно. Затем для каждого идентификатора все доступные поля, принадлежащие этому ключу, считываются из контейнера entriesи помещаются в выходную строку (переменнойLINE). Если значение для определенной комбинации идентификатора/столбца отсутствует, напишите вместо этого -NA-.

Затем выходные строки записываются в файл outfile.txt.

0
27.01.2020, 23:55

Один лайнер для выполнения в оболочке (/bin/sh или /bin/bash):

FILES="File1 File2 FILE3"; LIST=$(for F in ${FILES}; do cat ${F}|awk '{print $1}'; done|sort|uniq|xargs); for i in ${LIST}; do echo -n "$i"; for F in ${FILES}; do L=$(grep "^${i}\s" ${F}|head -1|sed 's/\t/ /'|cut -d' ' -f 2-|sed 's/^\s*//g'); [ -z "${L}" ] && echo -n " -NA-" || echo -n " ${L}" ; done; echo; done|sort

Выход:

MYORGANISM_I_00854.t1 TK-assoc/SH2/SH2-R -NA- -NA-
MYORGANISM_I_05140.t1 Atypical/PIKK/FRAP VALUES to be taken -NA-
MYORGANISM_I_06518.t1 CAMK/MLCK -NA- -NA-
MYORGANISM_I_12755.t1 TK-assoc/SH2/Unique -NA- -NA-
MYORGANISM_I_12766.t1 -NA- what -NA-
MYORGANISM_I_16941.t1 -NA- -NA- OK
MYORGANISM_I_93484.t1 -NA- -NA- LET IT BE

Пояснение:

# create list of files
# it can be created based on search like
# find. -type f -name filename.txt
# or something different
FILES="File1 File2 FILE3";
# create a list if unique first lines from all files from the list FILES
LIST=$(for F in ${FILES}; do cat ${F}|awk '{print $1}'; done|sort|uniq|xargs);
# take one by one each first line
# and go through all the files find corresponding lines endings
# and put them together
# or take '-NA-' for non-existing
for i in ${LIST}; do
    echo -n "$i";
    for F in ${FILES}; do
        #
        # old version of line commented out
        # L=$(grep "^${i}\s" ${F}|head -1|cut -d' ' -f 2-|sed 's/^\s*//g');
        # new version of line to make tab separator working
        L=$(grep "^${i}\s" ${F}|head -1|sed 's/\t/ /'|cut -d' ' -f 2-|sed 's/^\s*//g');
        #
        [ -z "${L}" ] && echo -n " -NA-" || echo -n " ${L}" ;
    done;
    echo;
done|sort
# sorted results printed
0
27.01.2020, 23:55

Вы можете использовать утилиту joinдважды, чтобы создать два "внешних соединения" для трех файлов. Предполагая, что все три файла разделены табуляцией -, сначала два первых файла:

$ join -a 1 -a 2 -o 0,1.2,2.2 -e '-NA-' -t $'\t' <( sort File1 ) <( sort File2 )
MYORGANISM_I_05140.t1   Atypical/PIKK/FRAP      VALUES to be taken
MYORGANISM_I_06518.t1   CAMK/MLCK       -NA-
MYORGANISM_I_00854.t1   TK-assoc/SH2/SH2-R      -NA-
MYORGANISM_I_12755.t1   TK-assoc/SH2/Unique     -NA-
MYORGANISM_I_12766.t1   -NA-    what

Это запрашивает утилиту joinобъединить отсортированные файлы в первом поле (, которое установлено по умолчанию ). Мы явно говорим -a 1 -a2, чтобы получить все строки из обоих файлов, даже если они не совпадают, а с помощью -o 0,1.2,2.2мы запрашиваем вывод, чтобы он состоял из поля соединения (, первого столбца )вместе со вторым. столбец каждого файла. Опция -e '-NA-'указывает, какой строкой заполнять пустые поля.

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

$ join -a 1 -a 2 -o 0,1.2,1.3,2.2 -e '-NA-' -t $'\t' tmpdata <( sort FILE3 )
MYORGANISM_I_00854.t1   TK-assoc/SH2/SH2-R      -NA-    -NA-
MYORGANISM_I_05140.t1   Atypical/PIKK/FRAP      VALUES to be taken      -NA-
MYORGANISM_I_06518.t1   CAMK/MLCK       -NA-    -NA-
MYORGANISM_I_12755.t1   TK-assoc/SH2/Unique     -NA-    -NA-
MYORGANISM_I_12766.t1   -NA-    what    -NA-
MYORGANISM_I_16941.t1   -NA-    -NA-    OK
MYORGANISM_I_93484.t1   -NA-    -NA-    LET IT BE

Это повторяет более или менее то же самое «внешнее соединение», что и раньше, но также добавляет дополнительный столбец с опцией -o.

0
27.01.2020, 23:55

Теги

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