Grep не возвращает одинаковые совпадения из awk pipe

Если вы откроете файл, содержащий определение функции автозагрузки для git completion:
В моей системе ubuntu это:

/usr/share/zsh/functions/Completion/Unix/_git

в верхней части файла вы увидите #compdef объявление

#compdef git git-cvsserver git-receive-pack git-upload-archive git-upload-pack git-shell gitk tig

вы можете попробовать добавить свои псевдонимы к #compdef определению, например,

#compdef git git-cvsserver git-receive-pack [...] tig gch grb
                                                      ^^^ ^^^

Затем запустите новый shell, чтобы загрузить эту новую директиву.
Затем попробуйте вызвать завершение.

What is /usr/share/zsh/functions/Completion/Unix/_git?

Это файл, который содержит автозагружаемую "функцию", определяющую поведение завершения для всех команд, определенных в директиве #compdef, в данном случае семейства команд git. Он находится в fpath и автозагружается compinit при инициализации системы завершения.

Что такое #compdef ?

из man zshcompsys

#compdef name ... [ -{p|P} шаблон ... [ -N имя ... ] ]
Файл будет сделан автозагружаемым, и определенная в нем функция будет вызываться при заполнении имен, каждое из которых либо является имя команды, аргументы которой должны быть заполнены, либо один из специальных контекстов в форме -context-, описанных ниже.

1
15.09.2017, 00:26
3 ответа

Именно для этого и предназначена команда join:она объединяет два файла на основе общего поля:

$ awk '{print $1}' File1 | join - File2

M01605:153:000000000-B55NK:1:1101:10003:14536 2:N:0:1 GTTTGCGCCGATGTA 
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC 
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC 
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT 
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT 
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT 
M01605:153:000000000-B55NK:1:1101:10010:14111 2:N:0:1 CTGCGTACTGATAGC 
M01605:153:000000000-B55NK:1:1101:10010:19939 2:N:0:1 TCCGTGGTGCCGGCA 
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG 
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG 

Ваши файлы могут быть отсортированы по номерам, но не по алфавиту, как ожидается join. Если joinжалуется, немного измените приведенную выше команду, чтобы отсортировать ввод с помощью GNU sort:

.
$ awk '{print $1}' File1 | sort | join - <(sort -k1,1 --stable File2)

Поскольку в вашем втором файле есть повторяющиеся строки (см. комментарии ), вы можете изменить вторую команду sortна sort -k1,1 --stable --unique File2(, по-прежнему предполагая, что вы используете GNU sort, используйтеuniq).

0
27.01.2020, 23:33

Как я интерпретирую ваш желаемый вывод, вы хотите, чтобы строки в Файле2 повторялись столько раз, сколько появляется первое поле в Файле1. Греп этого делать не будет. Вместо этого попробуйте:

$ awk 'FNR==NR{a[FNR]=$1;next} {for (k in a) if (a[k]==$1) print}' File1 File2
M01605:153:000000000-B55NK:1:1101:10003:14536 2:N:0:1 GTTTGCGCCGATGTA
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10010:14111 2:N:0:1 CTGCGTACTGATAGC
M01605:153:000000000-B55NK:1:1101:10010:19939 2:N:0:1 TCCGTGGTGCCGGCA
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG

Как это работает

  • FNR==NR{a[FNR]=$1;next}

    При чтении первого файла File1 сохраните первое поле $1в массиве aпод ключом номера строки FNR.

  • for (k in a) if (a[k]==$1) print

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

Более эффективная альтернатива

$ awk 'FNR==NR{a[$1]++;next} {for (i=1;i<=a[$1];i++) print}' File1 File2
M01605:153:000000000-B55NK:1:1101:10003:14536 2:N:0:1 GTTTGCGCCGATGTA
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10010:14111 2:N:0:1 CTGCGTACTGATAGC
M01605:153:000000000-B55NK:1:1101:10010:19939 2:N:0:1 TCCGTGGTGCCGGCA
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG
2
27.01.2020, 23:33

Предположим, что оба файла отсортированы одинаково по первому полю:

$ join -o1.1,1.2,1.3 file2 file1
M01605:153:000000000-B55NK:1:1101:10003:14536 2:N:0:1 GTTTGCGCCGATGTA
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC
M01605:153:000000000-B55NK:1:1101:10007:14573 2:N:0:1 GGGGATAAGCGTTGC
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10009:9160 2:N:0:1 CAGAAGAGGTAATGT
M01605:153:000000000-B55NK:1:1101:10010:14111 2:N:0:1 CTGCGTACTGATAGC
M01605:153:000000000-B55NK:1:1101:10010:19939 2:N:0:1 TCCGTGGTGCCGGCA
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG
M01605:153:000000000-B55NK:1:1101:10011:22802 1:N:0:1 TGAGTTCGGATAAAG

Будет выполнена операция реляционного соединения с использованием первого поля в качестве ключа. Выводимые поля указываются с флагом -oкак первые три поля первого файла (file2).

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


Сортировка важна. Вы должны либо предварительно -отсортировать файлы:

$ sort -o file1 file1
$ sort -o file2 file2

... или сортировать файлы на лету при вызовеjoin(требуется оболочка, которая понимает подстановку процессов с помощью <(...), напримерbash):

$ join -o1.1,1.2,1.3 <( sort file2 ) <( sort file1 )

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

0
27.01.2020, 23:33

Теги

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