Как добавить другую строку к дубликатам в одном столбце файла с разделителями табуляцией, чтобы сделать их уникальными

Программа установки Debian использует файловую систему ISO9660, которая неизменяема, вам потребуется переформатировать USB-накопитель, если вы хотите использовать его для общего хранения файлов.

например :в nautilus правой -щелкните диск и следуйте инструкциям

4
15.03.2021, 11:31
5 ответов

Попробуйте это

awk -F'\t' -v OFS='\t' '{$4=$4 "-" (++count[$4])}1' file.tsv

При этом будет сохранено появление каждого значения 4-го поля в массиве счетчиков count(, где значение 4-го поля используется как «индекс» ), и добавлено предварительно -увеличенное значение этого счетчик до 4-го поля, разделенного тире.

Приведенный выше «простой» пример имеет недостаток :: он добавляет число устранения неоднозначности даже к тем значениям в столбце 4, которые встречаются в файле только один раз. Чтобы подавить это, следующий подход с двойным -проходом будет работать (командой, разбитой на две строки через \для улучшения читаемости):

 awk -F'\t' -v OFS='\t' 'NR==FNR{f[$4]++}\
      NR>FNR{if (f[$4]>1) {$4=$4 "-" (++count[$4])}; print}' file.tsv file.tsv

Обратите внимание, что обрабатываемый файл указывается дважды в качестве аргумента и, следовательно, будет прочитан дважды.

  • При первом чтении (, обозначенном FNR, счетчик строки файла -, равный NR, глобальный счетчик строки ), мы просто подсчитываем, как часто каждое отдельное значение столбца 4 появляется в файле и сохраняет его в массиве f.
  • При втором чтении файла мы выполняем фактическую обработку текста так же, как и в «простом» подходе, и добавляем счетчик вхождений в столбец 4, но только если общее количество вхождений, найденное в первом проходе, больше. чем 1.

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

Как правило, использование циклов оболочки для обработки текста требуется редко, awkнапример.может выполнять циклические операции самостоятельно гораздо более эффективным способом.

7
18.03.2021, 23:19

Это только добавляет "-номер " к указанному (целевому )полю (четвертому в вашем образце ), если его значение не уникально. Он также обрабатывает случай ввода, не отсортированного по целевому столбцу, и работает для произвольного количества входных столбцов.

Так как следующий сценарий AWK требует сортировки ввода по целевому полю, мы используем конвейер для нумерации исходных строк, сортируя их по (сейчас )пятому полю (первое из которых добавлено номер ), добавьте суффикс к не -уникальным значениям пятого поля, верните строки к исходной сортировке и удалите добавленные числа:

nl file | sort -b -t '<TAB>' -k5,5 -k1n,1n | awk -F '\t' -v OFS='\t' -v kf=5 '
  function prn () {
    for (i = 1; i <= nfl; i++) {
      if (i == kf)
        printf("%s", prc[i] ( sw || cnt[prc[i]] ? "-"++cnt[prc[i]] : ""))
      else
        printf("%s", prc[i])
      printf("%s", (i == nfl ? ORS : OFS))
    }
  }
  NR > 1 {
    sw = ($kf == prc[kf])
    prn()
  }
  {
    nfl = split($0, prc)
  }
  END {
    if (NR > 0)
      prn()
  } ' | sort -k1n,1n | cut -f 2-

Суть этого AWK-скрипта состоит в том, чтобы напечатать предыдущую строку после проверки того, совпадает ли ее kf-е поле с полем текущей строки или ее kf-е поле уже появилось в не реже одного раза. В обоих случаях kf-е поле печатается с добавленным к нему числом просмотров.

Обязательно отрегулируйте-v kf=5(и клавишу-k5,5sort)так, чтобы они отражали фактическое положение столбца, в котором вы хотите устранить неоднозначность.

Учитывая этот образец (ваш, с перетасованными строками и добавленным столбцом )какfile:

chr7    116038644   116039744   GeneA   foo
chrX    143933024   143934124   GeneB   foo
chr7    116030947   116032047   GeneA   foo
chr7    115824610   115825710   GeneA   foo
chrY    143933129   143933229   GeneC   foo
chr7    115994986   115996086   GeneA   foo
chrX    143933119   143934219   GeneB   foo
chr7    115801509   115802609   GeneA   foo
chr7    115846040   115847140   GeneA   foo

вывод будет:

chr7    116038644   116039744   GeneA-1 foo
chrX    143933024   143934124   GeneB-1 foo
chr7    116030947   116032047   GeneA-2 foo
chr7    115824610   115825710   GeneA-3 foo
chrY    143933129   143933229   GeneC   foo
chr7    115994986   115996086   GeneA-4 foo
chrX    143933119   143934219   GeneB-2 foo
chr7    115801509   115802609   GeneA-5 foo
chr7    115846040   115847140   GeneA-6 foo
2
18.03.2021, 23:19

Предположим, что ваш входной файл сгруппирован по 4-му столбцу, как показано в вашем примере:

$ cat tst.awk
$NF != prev {
    prt()
    cnt = 0
    prev = $NF
}
{ rec[++cnt] = $0 }
END { prt() }

function prt() {
    for (i=1; i<=cnt; i++) {
        print rec[i] (cnt > 1 ? "-"i : "")
    }
}

.

$ awk -f tst.awk file
chr7    116038644       116039744       GeneA-1
chr7    116030947       116032047       GeneA-2
chr7    115846040       115847140       GeneA-3
chr7    115824610       115825710       GeneA-4
chr7    115801509       115802609       GeneA-5
chr7    115994986       115996086       GeneA-6
chrX    143933024       143934124       GeneB-1
chrX    143933119       143934219       GeneB-2
chrY    143933129       143933229       GeneC
4
18.03.2021, 23:19

шаг 1:

awk '{a[$NF]++}END{for (x in a) {print x,a[x]}}' filename| awk '{if($NF >1){for(i=1;i<=$2;i++){print $1"-"i}}else{print $1}}' >first.txt

шаг 2:

awk '{$NF="";print $0}' filename >second.txt

шаг 3:

paste second.txt first.txt | sed -r "s/\s+/ /g"

выход

chr7 116038644 116039744 GeneA-1
chr7 116030947 116032047 GeneA-2
chr7 115846040 115847140 GeneA-3
chr7 115824610 115825710 GeneA-4
chr7 115801509 115802609 GeneA-5
chr7 115994986 115996086 GeneA-6
chrX 143933024 143934124 GeneB-1
chrX 143933119 143934219 GeneB-2
chrY 143933129 143933229 GeneC

питон

#!/usr/bin/python
j=[]
ww=[]
k=open('rrr.txt','r')
for i in k:
    if i.split(' ')[-1].strip() not in j:
        j.append(i.split(' ')[-1].strip())


for g in j:
    h=open('rrr.txt','r')
    d=h.readlines()
    for e in d:
        if g in e.strip():
            ww.append(e.strip())
    if len(ww) > 1:
        for z in  range(0,len(ww),1):
            print "{0}-{1}".format(ww[z],z+1)
            
    else:
        print "".join(ww)
    ww=[]

выход

chr7    116038644       116039744       GeneA-1
chr7    116030947       116032047       GeneA-2
chr7    115846040       115847140       GeneA-3
chr7    115824610       115825710       GeneA-4
chr7    115801509       115802609       GeneA-5
chr7    115994986       115996086       GeneA-6
chrX    143933024       143934124       GeneB-1
chrX    143933119       143934219       GeneB-2
chrY    143933129       143933229       GeneC
1
18.03.2021, 23:19

Простая двухпроходная -команда awk:

$ awk -F '\t' '
    BEGIN { OFS=FS }
    pass == 1 { count[$4]++; next }
    count[$4] > 1 { $4 = $4 "-" ++number[$4] }; 1' pass=1 file pass=2 file
chr7    116038644       116039744       GeneA-1
chr7    116030947       116032047       GeneA-2
chr7    115846040       115847140       GeneA-3
chr7    115824610       115825710       GeneA-4
chr7    115801509       115802609       GeneA-5
chr7    115994986       115996086       GeneA-6
chrX    143933024       143934124       GeneB-1
chrX    143933119       143934219       GeneB-2
chrY    143933129       143933229       GeneC

Предполагается, что входной файл разделен табуляцией -. Измените или удалите -F '\t', если это не так.

При первом проходе по файлу ассоциативный массив countзаполняется числом раз, когда каждое имя гена встречается в четвертом столбце.

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

Добавленное число — это еще один счетчик, также включаемый именем гена, как и в массиве counter.

0
18.03.2021, 23:19

Теги

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