У вас 3 варианта:
1-й это рекомендуемый способ.
Это чистое решение на awk, которое работает для двух шаблонов на строку (разделенных пробелами) в файле шаблонов с операцией логического И:
awk 'NR==FNR{patts[$1]=$2;next}{for (i in patts) if (($0 ~ i) && ($0 ~ patts[i])) print}' patterns file
Обновление :
Для сопоставления слова вместо регулярного выражения вы можете оценить эту альтернативу:
awk 'NR==FNR{patts[$0]="\\<" $1 "\\>.*\\<" $2 "\\>|\\<" $2 "\\>.*\\<" $1 "\\>";next} \
{for (i in patts) if ($0 ~ patts[i]) print}' patterns file1
Фактически он преобразует шаблон 833 7777
в
\ <833 \>. * \ <7777 \> | \ <7777 \>. * \ <833 \>
, который выполняет сопоставление слов и имитирует также логическое И для двух шаблонов.
Это решение протестировано и не соответствует записям типа G 77771 2833
Обновление №2
Это обеспечит сопоставление слов, операцию логического И и печать для сопоставленных групп с разделительной строкой.
awk 'NR==FNR{patts[$0]="\\<" $1 "\\>.*\\<" $2 "\\>|\\<" $2 "\\>.*\\<" $1 "\\>";next} \
{for (i in patts) {if ($0 ~ patts[i]) !found[i]?found[i]=$0:found[i]=found[i] ORS $0}} \
END{for (k in found) {print found[k];print "-----"}}' patterns file1
#Output
A 833 0 0 0 0 7777 0 0 0 0
F 7777 833
-----
D illicit Jam fox 33333
-----
C the cow jumps over the 311 moon 2222
-----
PS: Из-за awk-способа работы с ассоциативными массивами мы не можем повлиять в секции END на печать найденного массива. Будет как-то «случайным».
Если известно, что в каждой строке файла file1 ровно две строки:
while read -ra elements; do
grep "${elements[0]}" file2 | \
grep "${elements[1]}" && \
echo "----"
done < file1
perl -wMstrict -Mvars='*f2' -l -0777ane '
if ( ! @ARGV ) {# this is File1 zone: slurped in $_
while ( /^(\S+)\s+(\S+)$/mg ) {
my $rx = qr/^(?=.*$1)(?=.*$2)/m; # AND matching of $1/$2
pos($f2)=0;
$f2 =~ /\G([^\n]+)/m and print $1 while $f2 =~ /$rx/mg;
print "--- <Separator> ---" unless /\G\n\z/;
}
} else {# This is File2 zone: slurped whole in $f2
$f2 = $_;
}
' File2 File1 #<----- order is important here
Мы должны помнить о порядке печати. здесь очень важно. Строки File2 печатаются в порядке, определяемом строками, которые должны быть найдены в File1. И после того, как каждая строка File1 сопоставляется с шаблоном File1, нам также нужна разделительная линия, независимо от того, было ли совпадение успешным или нет. Файлы прихлебываются, File2 => $ f2, и File обрабатывается как $ _ in
Здесь можно сделать трюк, который отлично работает в моих тестах:
$ awk -f <(sed 's/^\|$/\//g; s/ /\/ \&\& \//g' file1) file2
#Output
A 833 0 0 0 0 7777 0 0 0 0
C the cow jumps over the 311 moon 2222
D illicit Jam fox 33333
F 7777 833
Успех этого решения заключается в том, что мы преобразуем файл1 (паттерны) в формат awk /pattern1/ && /pattern2/{print}
(print - действие по умолчанию, его можно опустить)
$ sed 's/^\|$/\//g; s/ /\/ \&\& \//g' file1
/311/ && /2222/
/833/ && /7777/
/Jam/ && /33333/
Вместо того, чтобы писать с помощью sed новый файл, мы передаем sed непосредственно в awk как файл, используя подстановку процесса.
Так команда :
awk -f <(sed 's/^\|$/\//g; s/ /\/ \&\& \//g' file1) file2
инструктирует awk прочитать программу из подзаголовка процесса и применить ее к файлу2.
Обратите внимание, что я пропустил разделители, поскольку неясно, где именно они нужны.
PS: Это, конечно, должно быть чисто awk-решение.
Я бы сделал это в perl
, потому что мне кажется, что так понятнее:
#!/usr/#bin/env perl
use strict;
use warnings;
use Data::Dumper;
my ( $pattern_file_name, $process_file_name ) = @ARGV;
open ( my $patterns_file, '<', $pattern_file_name ) or die $!;
my @matches = map { [split] } <$patterns_file>;
close ( $patterns_file );
print "Using:\n";
print Dumper \@matches;
#my @matches = ( [ '311', '2222' ], [ '833', '7777' ], [ 'Jam', '33333' ] );
#read main file
my @results;
open ( my $input, '<', $process_file_name ) or die $!;
#iterate a line at a time.
while ( my $line = <$input> ) {
GROUP:
for my $id ( 0 .. $#matches ) {
#Check each set of expressions.
foreach my $expression ( @{ $matches[$id] } ) {
#move to the next group if any don't match
next GROUP unless $line =~ m/$expression/;
}
#didn't get skipped, so must have matched all.
push( @{ $results[$id] }, $line );
}
}
print Dumper \@results;
print "\n$_\n" for @results;
close ( $input );