#awk
#awk
Вопрос:
Я пытаюсь использовать awk для имитации uniq -d
в определенных полях для печати строки, которая в данный момент читается, а также предыдущей строки, используя первое решение из здесь, но, похоже, оно печатает одну и ту же строку дважды.
Вот пример содержимого файла.
130 chr1 7237 7238 0k9imgkt
135 chr1 7637 7637 b9gko
138 chr1 7908 7908 kob9g
139 chr1 8045 8045 34e5rg 4r
151 chr1 8329 8329 b
151 chr1 8346 8346 345y46htyh
151 chr1 8346 8346 76jtuj
152 chr1 8358 8358 asfge
Вот строка, которую я использовал. Я пытаюсь сравнить строки на основе второго, третьего и четвертого полей; если две или более строк идентичны в этих полях, распечатайте все эти строки целиком. Кроме того, можно с уверенностью предположить, что строки отсортированы на основе полей 1, 2 и 3.
awk '{prev = $0; array[$2$3$4]; if(array[$2$3$4] == 2) {print; curr = $0; $0 = prev; print; $0 = curr}}' file
Вот каким я хочу быть результат.
151 chr1 8346 8346 345y46htyh
151 chr1 8346 8346 76jtuj
И вот какой результат.
151 chr1 8346 8346 76jtuj
151 chr1 8346 8346 76jtuj
Комментарии:
1. Я допустил ошибку при вводе этой строки; Я исправил ее.
2. Каким должен быть результат, если в конце вашего опубликованного образца ввода появилась строка типа
153 chr1 8045 8045 foo
? Следует ли печатать более раннюю139 chr1 8045 8045 34e5rg 4r
строку, а затем эту новую строку, поскольку оба имеют общие значения $ 2 / $ 3 / $ 4? Если да, то где она должна появиться — перед 151 строкой или после них?
Ответ №1:
Если я правильно понял ваш вопрос, не могли бы вы попробовать следующее.
awk 'FNR==NR{a[$2$3$4] ;next} a[($2$3$4)]>1' Input_file Input_file
или
awk '{k=$2 FS $3 FS $4} FNR==NR{a[k] ;next} a[k]>1' Input_file Input_file
Вывод будет следующим.
151 chr1 8346 8346 345y46htyh
151 chr1 8346 8346 76jtuj
Комментарии:
1. @DangIt, не могли бы вы попробовать это один раз и сообщить мне, поможет ли это вам?
2. Я не уверен, почему, но для меня результатом является пустой файл.
3. @DangIt, не могли бы вы, пожалуйста, сообщить мне, если вы упомянули Input_file 2 раза? Я читаю файл 2 раза.
4. Вы правы; я забыл вставить это во второй раз. Почему мне нужно ввести входной файл дважды? Например, были бы какие-либо преимущества в возможности вызова двух разных входных файлов?
5. Он проверяет, какие ключи существуют несколько раз в файле, а затем на втором проходе печатает их. Циклы teo неэффективны, но позволяют обрабатывать файлы, в которых дубликаты могут быть не смежными.
Ответ №2:
Вы печатаете одну и ту же строку дважды. Не совсем ясно, какой вы хотите видеть логику, но, безусловно, одно из print
утверждений должно быть print curr
или, возможно print prev
. Также одинокий prev
ничего не делает и выглядит так, как будто он остался из-за ошибки редактирования.
Возможно, вы ищете что-то вроде
awk ' array[$2$3$4] >= 2 {
if(prev)print prev;
print;
prev = ""; next }
{ prev = $0 }' file
Если это не делает того, что вы хотите, возможно, отредактируйте свой вопрос, чтобы более подробно описать, что, как вы надеетесь, должен делать ваш текущий скрипт; код, который не делает то, что вы хотите, на самом деле не является хорошим способом сообщить, что вы хотите.
Комментарии:
1. Какова цель
prev = ""
? Для меня похоже, что{prev = $0}
это все равно перезапишется.2. Это делается для того, чтобы избежать печати
prev
более одного раза при третьем или четвертом повторении.next
Обходит блок, содержащийprev = $0
назначение.3.
a bc
->abc
.ab c
->abc
. При создании уникальных ключей путем объединения полей вам необходимо включить разделители:{k=$2 FS $3 FS $4}
.4. Это хорошее решение, если поля на самом деле могут быть неоднозначными. Пример данных выглядит так, как будто второе поле не будет сильно отличаться.
5. Я не уверен, что
chrN
всегда будет заканчиваться цифрой 1 против 2, и что числовые столбцы всегда состоят из 4 цифр против 3 или 5 или чего-то еще, но, возможно, я просто параноик, idk.
Ответ №3:
Вот еще одно решение awk, которое не считывает входной файл дважды и работает, даже если ваш ввод не отсортирован.
awk '(k = $2 FS $3 FS $4) in a {
print a[k] $0; a[k] = ""; next
} { a[k] = $0 ORS }' file
Комментарии:
1. Используя полный набор данных, он корректно работает для первой пары дубликатов, но после этого выводит только второй дубликат каждой пары дубликатов.
2. @DangIt в это трудно поверить, если только ключи $ 2/3/4 не могут повторяться в последующих строках. Вы должны включить этот вариант использования в свой опубликованный образец ввода / вывода, чтобы люди могли протестировать потенциальные решения на нем.