Как сортировать по нечетным строкам и затем удалять повторяющиеся значения?

Вы можете использовать NR и FNR в awk.

awk 'FNR==NR { _a[FNR]=$3;} NR!=FNR { $4 += _a[FNR]; print;  }'  file1 file2
7
18.01.2019, 15:38
6 ответов

Не совсем тот порядок сортировки, который вы показали, но, может быть, тоже верно?

$ cat input.txt|paste - -| sort -k1,1V -k2,2| tr "\t" "\n" | awk '{if($0 in line == 0) {line[$0]; print}}'
    transcr_7135 +
    YBL029C-A -
    YBL029W +
    transcr_11317 +
    YBL067C -
    transcr_20649 +
    YBL100C -
    transcr_25793 +
    YAL037C-B -
    YAL038W +
    YAL039C -

РЕДАКТИРОВАТЬ:

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

$ cat input.txt | paste - - | nl | sort -k2,2V -k1,1g | cut -f2- | tr "\t" "\n" | awk '{if($0 in line == 0) {line[$0]; print}}'
3
27.01.2020, 20:15

С GNU sortи при условии, что строки не содержат символов TAB:

paste - - < file | sort -V | tr '\t' '\n' | awk '!seen[$0]++'

Или sort -t$'\t' -sk1,1V, чтобы сохранить исходный порядок записей с идентичными нечетными строками, как в ожидаемом результате.

Если у вас нет GNU sortи предполагается, что нечетные строки всегда следуют этому шаблону, вы можете заменить sort -Vна sort -k1.9n.

3
27.01.2020, 20:15

Чистый gawkраствор:

awk -F_ 'NR%2{i=$2;next}{a[i]=a[i]"\n"$0}
         END{PROCINFO["sorted_in"]="@ind_num_asc";
             for(i in a) printf "%s","transcr_"i""a[i]"\n"}' file

Хитрость заключается в численной сортировке индексов массива aс небольшой помощью специального массива gawkPROCINFO.

transcr_7135
YBL029C-A -
YBL029W +
transcr_11317
YBL067C -
transcr_20649
YBL100C -
transcr_25793
YAL039C -
YAL037C-B -
YAL038W +

Кстати, жаль, что awk не предлагает возможность естественной сортировки, также известной как сортировка версии(по тексту с номерами ).

7
27.01.2020, 20:15

Предварительная -и постобработка с помощью awk; это не предполагает, что за строкой transcrследует только одна строка Y*; он также идемпотент --, его вывод может быть передан обратно в качестве ввода, и он даст тот же результат.

awk '{print $0~/^transcr/ ? t=$0 : t" "$0}' /tmp/foo | sort -t_ -k2n -k2 -u | awk '{print (NF > 2) ? $3" "$4 : $0}'
transcr_7135 +
YBL029C-A -
YBL029W +
transcr_11317 +
YBL067C -
transcr_20649 +
YBL100C -
transcr_25793 +
YAL037C-B -
YAL038W +
YAL039C -
0
27.01.2020, 20:15
for element in $(sed -n 'p;n' a.txt |sort -nk 1.9 |uniq |awk '{print $1}')
do
    echo $element; cat a.txt |grep -A1 $i |grep -v trans |grep -v \\\\--
done

Где.txt — ваш ввод. Проверено:

[root@megatron ~]# cat a.txt
transcr_25793 +
YAL039C -
transcr_25793 +
YAL037C-B -
transcr_20649 +
YBL100C -
transcr_7135 +
YBL029C-A -
transcr_11317 +
YBL067C -
transcr_25793 +
YAL038W +
transcr_7135 +
YBL029W +
[root@megatron ~]# for i in $(sed -n 'p;n' a.txt |sort -nk 1.9 |uniq |awk '{print $1}')
do
echo $i; cat a.txt |grep -A1 $i |grep -v trans |grep -v \\\\--
done
transcr_7135
YBL029C-A -
YBL029W +
transcr_11317
YBL067C -
transcr_20649
YBL100C -
transcr_25793
YAL039C -
YAL037C-B -
YAL038W +
[root@megatron ~]#
2
27.01.2020, 20:15

Позвольте мне еще раз сформулировать вашу проблему. Вы действительно хотите сделать две операции:

  • Сортировать нечетные -пронумерованные(transcr*)строки по номеру в строке, сохраняя четные -пронумерованные(Y*)строки, связанные с предыдущей строкой
  • Объединить все Y*строки, подпадающие под одинаковые transcr*строки

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

Этот скрипт примет ваш ввод и создаст строки, идентичные вашему окончательному выводу:

#!/bin/env python

from collections import defaultdict
import fileinput
import re

def pair_lines (iterable):
    ''' Return lines two at a time '''
    args = [iterable] * 2;
    return zip(*args)

dd = defaultdict(list)
for line1,line2 in pair_lines(fileinput.input()):
    # accumulate lists of all second lines that share the same first
    # line value
    dd[line1].append(line2)

def line_index (line):
    ''' Return first substring that looks like an integer '''
    return int(re.search(r'\d+',line).group(0))

# sort by first lines and print results
for line1 in sorted(dd.keys(), key=line_index):
    print(line1, *dd[line1], end='', sep='')

Выполнить с помощью:

reorder.py input.txt > output.txt 
0
27.01.2020, 20:15

Теги

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