Использовать grep только для определенных столбцов во многих файлах? - PullRequest
1 голос
/ 21 июня 2019

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

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

Вывод, такой как:

pattern1
file23:"text from entire line in file 23 here"
file37:"text from entire line in file 37 here"
file156:"text from entire line in file 156 here"
pattern2
file12:"text from entire line in file 12 here"
file67:"text from entire line in file 67 here"
file200:"text from entire line in file 200 here"

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

Я думал об этом:

cat pattern_file.txt | while read line
do
  echo $line >> output.txt
  zgrep -w -l $line many_files/*txt >> output.txt
done

Но с этим кодом он не выполняет поиск только по первым двум столбцам. Есть ли способ, чтобы указать первые два столбца как для строки шаблона, так и для строк, которые просматривает grep?

Каков наилучший способ сделать это? Будет ли лучше использовать что-то кроме grep, например awk? Были и другие подобные вопросы, но ни один из них не использовал столбцы как для шаблона поиска, так и для искомого файла.

Несколько строк из файла шаблона:

1 5390182 . A C 40.0 PASS DP=21164;EFF=missense_variant(MODERATE|MISSENSE|Aag/Cag|p.Lys22Gln/c.64A>C|359|AT1G15670|protein_coding|CODING|AT1G15670.1|1|1) 
1 5390200 . G T 40.0 PASS DP=21237;EFF=missense_variant(MODERATE|MISSENSE|Gcc/Tcc|p.Ala28Ser/c.82G>T|359|AT1G15670|protein_coding|CODING|AT1G15670.1|1|1) 
1 5390228 . A C 40.0 PASS DP=21317;EFF=missense_variant(MODERATE|MISSENSE|gAa/gCa|p.Glu37Ala/c.110A>C|359|AT1G15670|protein_coding|CODING|AT1G15670.1|1|1) 

Несколько строк из файла в найденных файлах:

1   10699576    .   G   A   36  PASS    DP=4    GT:GQ:DP    1|1:36:4
1   10699790    .   T   C   40  PASS    DP=6    GT:GQ:DP    1|1:40:6
1   10699808    .   G   A   40  PASS    DP=7    GT:GQ:DP    1|1:40:7

Они оба на самом деле намного крупнее.

Ответы [ 2 ]

4 голосов
/ 21 июня 2019

Похоже, это то, что вы хотите:

awk 'NR==FNR{a[$1,$2]; next} ($1,$2) in a' patternfile anyfile

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

если anyfile на самом деле является zip-файлом, то вы бы сделали что-то вроде:

zcat anyfile | awk 'NR==FNR{a[$1,$2]; next} ($1,$2) in a' patternfile -

Замените zcat любой командой, которую вы используете для создания текста из вашего zip-файла, если это не то, что вы используете.

В соответствии с вопросом в комментариях, если оба входных файла сжаты и ваша оболочка поддерживает это (например, bash), вы можете сделать:

awk 'NR==FNR{a[$1,$2]; next} ($1,$2) in a' <(zcat patternfile) <(zcat anyfile)

в противном случае просто сначала распакуйте файл-шаблон в файл tmp и используйте его в команде awk.

0 голосов
/ 21 июня 2019

Используйте read для анализа столбцов файла шаблона и добавления привязки к шаблону zgrep:

while read -r column1 column2 rest_of_the_line
do
  echo "$column1 $column2 $rest_of_the_line" 
  zgrep -w -l "^$column1\s*$column2" many_files/*txt
done < pattern_file.txt >> output.txt

read может анализировать строки в несколько переменных, переданных в качестве параметров, последнийиз которых получить остальную часть линии.Он разделяет поля вокруг символов внутреннего разделителя полей $IFS (по умолчанию табуляции, пробелы и переводы строк могут быть переопределены для команды read с помощью while IFS='...' read ...).

Использование -r позволяет избежатьнежелательные побеги делают анализ более надежным, а while ... do ... done < file работает немного лучше, поскольку позволяет избежать бесполезного использования cat.Поскольку вывод всех команд из while перенаправлен, я также назначил перенаправление на while, а не на каждую отдельную команду.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...