Выберите только первые строки, которые содержат повторную строку

У меня есть файл, который похож на это:

2_00003 R034671 31.25   96  55  2   100 195 77  161 7e-07   47.8
2_00003 R034668 31.25   96  55  2   100 195 77  161 7e-07   47.8
2_00003 R034667 31.25   96  55  2   100 195 77  161 7e-07   47.8
2_00003 R034665 31.25   96  55  2   100 195 77  161 7e-07   47.8
2_00003 R034656 34.88   86  45  2   100 185 77  151 9e-07   47.4
2_00003 R034662 34.88   86  45  2   100 185 77  151 9e-07   47.4
2_00003 R034659 34.88   86  45  2   100 185 77  151 9e-07   47.4
2_00004 R014991 31.90   232 141 5   2   232 4   219 5e-28    111
2_00004 R009910 31.90   232 141 5   2   232 4   219 5e-28    111

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

2_00003 R034671 31.25   96  55  2   100 195 77  161 7e-07   47.8
2_00004 R014991 31.90   232 141 5   2   232 4   219 5e-28    111

Я думавший использовать просто

uniq -w 7 <file name>

Но у меня есть две проблемы:

  1. Я не уверен если uniq отчеты всегда первое вхождение (в моем случае в первой строке)
  2. иногда в моем файле строка в первом столбце имеет много символов выше, чем 7, таким образом, моя идея не будет работать

Совет?

0
задан 6 February 2015 в 10:47

4 ответа

Вы можете рассмотреть использование sort -u в качестве альтернативы uniq, указав в качестве ключа первое поле, разделенное пробелами:

$ sort -uk1,1 file
2_00003 R034671 31.25   96  55  2   100 195 77  161 7e-07   47.8
2_00004 R014991 31.90   232 141 5   2   232 4   219 5e-28    111

В качестве альтернативы, вы можете сделать что-то подобное в awk:

awk '$1!=last {last=$1; print}' file

, который проверяет первое поле каждой строки ($1) на соответствие значению last и печатает строку при каждом изменении $1, обновляя значение last по мере его поступления. [ 1111]

3
ответ дан 6 October 2019 в 02:13

Можно сделать это в сценарии как это:

first_occurence.sh (устанавливает его, чтобы быть исполняемым файлом)

#!/bin/bash

# Set bash to separate words by newlines only, not spaces
IFS= 

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

./first_occurence.sh < filename 
\n' # read input input=("$(cat)") # get a list of unique keys - split input by space with awk for any length unique_values=($(printf "%s\n" "${input[*]}" | awk -F' ' '{ print $1 }' | uniq)) cur=0 # check each line of input for the key for line in ${input[@]}; do # wildcard matching if [[ "$line" == "${unique_values[$cur]}"* ]] then # print line if match, and move on to checking the next key printf "%s\n" "$line" cur=$((cur + 1)) fi # break the loop if we have used up all of our unique keys (only duplicates remain) if [ $cur -ge ${#unique_values[@]} ] then break fi done

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

./first_occurence.sh < filename 
0
ответ дан 6 October 2019 в 02:13

Я думаю, что решение Steeldriver с использованием sort является лучшим, хотя, если вы хотите попробовать что-то еще, проверьте следующий скрипт Python:

#!/usr/bin/python2
import re
def checking():
        if not check_list:
            result.append(list_of_lines[index - 1])
with open('/path/to/the/file') as f:
    list_of_lines = f.readlines()
    result = []
    for index in range(1, len(list_of_lines)):
        regex_current = re.search('^[0-9]_[0-9]+', list_of_lines[index])
        regex_previous = re.search('^[0-9]_[0-9]+', list_of_lines[index - 1])
        check_list = [x for x in result if x.split()[0] == regex_previous.group()]
        if regex_current == regex_previous:
            checking()
        else:
            checking()
print ''.join(result)
0
ответ дан 6 October 2019 в 02:13

Другой подход Python:

  • считайте файл
  • перечислите уникальные случаи первого столбца
  • перечислите первое вхождение в списке
#!/usr/bin/env python3
import sys
file = sys.argv[1]

with open(file) as src:
    lines = src.readlines()
for l in [[l for l in lines if l.startswith(f)][0] for f in set([l.split()[0] for l in lines])]:
    print(l, end = "")

Выполните его с текстовым файлом как аргумент:

python3 <script> <text_file>

Примечание:

Хотя опция выше оказывается быстрым (протестированный на файле> 1 000 000 строк), это может быть решительно быстрее (appr. 15% в тестах, которые я запустил), если мы можем принять строку в первом столбце, не происходит на других положениях в записях (вероятно, безопасное предположение). В этом случае мы можем пропустить startswith() функция:

#!/usr/bin/env python3
import sys
file = sys.argv[1]

with open(file) as src:
    lines = src.readlines()
for l in [[l for l in lines if f in l][0] for f in set([l.split()[0] for l in lines])]:
    print(l, end = "")
1
ответ дан 6 October 2019 в 02:13

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

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