Получение шаблонов из файла, сравнение со столбцом другого файла, печать совпадающих строк с помощью 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

здесь , - это разделитель.