Получение шаблонов из файла, сравнение со столбцом другого файла, печать совпадающих строк с помощью awk
Я бы по существу хотел объединить силу
grep -f
С
awk '{ if(=="this is where I'd like to input a file of fixed string patterns") print }'
то есть, я хотел бы найти определенный столбец файла (файл 1) с входным файлом шаблонов (файл 2). Если совпадение найдено просто:
> outputfile.txt
из предыдущего сообщения эта строка awk действительно близка:
awk 'NR==FNR{a[]=1;next} {n=0;for(i in a){if(~i){n=1}}} n' file1 file2
принято от получить шаблоны в одном файле из другого с помощью ack или awk или лучше, чем греп?
но он не ищет определенный столбец файла 1. Я открыт и для других инструментов.
3 ответов
пример, который вы нашли, действительно очень близок к тому, что вы хотите, единственная разница в том, что вы не хотите соответствовать всей строке ().
изменить его на что-то вроде этого:
awk 'NR==FNR { pats[]=1; next } { for(p in pats) if( ~ p) { print ; break } }' patterns file
Если вам нужно только фиксированное совпадение строк, используйте ]=1; next } { for(p in pats) if($col ~ p) { print ; break } }' patterns file
редактировать-все поле соответствие
вы можете сделать это с помощью ==
оператор:
awk -v col=$col 'NR==FNR { pats[]=1; next } { for(p in pats) if($col == p) { print ; break } }' patterns file
это с помощью awk
:
awk 'BEGIN { while(getline l < "patterns.txt") PATS[l] } in PATS' file2
здесь file1
- файл, который вы ищете, и patterns.txt
- это файл с одним точным шаблоном на файл. Неявное {print}
был опущен, но вы можете добавить его и сделать все, что вам нравится там.
условие in PATS
будет true, второй столбец является точно одним из шаблонов.
если patterns.txt
должны рассматриваться как совпадения с регулярным выражением, измените его на
ok=0;{for (p in PATS) if ( ~ p) ok=1}; ok
так, например, в тест против всех регулярных выражений в
patterns.txt
, и печатать
третий столбец, если 2-й столбец соответствует:
awk 'BEGIN { while(getline l < "patterns.txt") PATS[l] }
ok=0;{for (p in PATS) if ( ~ p) ok=1}; ok
{print }' < file2
а вот версия в perl
. Похожие на awk
версия за исключением того, что он
использует регулярные выражения вместо поля.
perl -ne 'BEGIN{open $pf, "<patterns.txt"; %P=map{chomp;$_=>1}<$pf>}
/^\s*([^\s]+)\s+([^\s]+).*$/ and exists $P{} and print' < file2
разбирая это на части:
BEGIN{
open $pf, "<patterns.txt";
%P = map {chomp;$_=>1} <$pf>;
}
читает в вашем файле шаблонов в has %P
для быстрого поиска.
/^\s*([^\s]+)\s+([^\s]+).*$/ and # extract your fields into , , etc
exists $P{} and # See if your field is in the patterns hash
print; # just print the line (you could also
# print anything else; print "\n"; etc)
становится немного короче, если ваш входной файл tab-разделены (и когда вы знаю что между полями есть ровно одна вкладка). Вот пример, который соответствует модели против 5-й:
perl -F"\t" -ane '
BEGIN{open $pf, "<patterns.txt"; %P=map{chomp;$_=>1}<$pf>}
exists $P{$F[4]} and print ' file2
это благодаря perl -F
оператор, который сообщает perl для автоматического разделения на столбцы
на основе разделителя (\t
в данном случае).
Обратите внимание, что поскольку массивы в perl
запустить от 0
, $F[4]
это 5-е поле.
Я не совсем уверен, какую роль играет различие столбцов в этом сценарии. Вы обрабатываете какой-то csv-файл? Вы заботитесь о разделителях столбцов в файле списка регулярных выражений? Если в вашем файле нет отдельных столбцов, разделенных определенными разделителями, вы можете просто использовать grep
:
grep -o -f file2 file1
если столбцы являются проблемой, возможно, что-то вроде этого:
grep -o "[^,]*" file1 | grep -f file2
здесь ,
- это разделитель.