Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Match multiple patterns in any order (Perl)

Tags:

regex

perl

I have a file that looks like (but a LOT bigger):

arbstring1014: 120|PROKKA_00511 630|PROKKA_01218 630|PROKKA_01999 630|PROKKA_00506
arbstring1015: 120|PROKKA_02025 630|PROKKA_03113 120|PROKKA_02363 196|PROKKA_02308
arbstring1016: 120|PROKKA_02059 196|PROKKA_03630 630|PROKKA_03589 630|PROKKA_00462
arbstring1017: 120|PROKKA_02961 196|PROKKA_03061 630|PROKKA_03283 120|PROKKA_03099
arbstring1025: 120|PROKKA_02979 196|PROKKA_02928 630|PROKKA_03158
arbstring1026: 120|PROKKA_00924 196|PROKKA_00857 630|PROKKA_00906
arbstring1027: 120|PROKKA_02739 196|PROKKA_02684 630|PROKKA_02848
arbstring1028: 120|PROKKA_01415 196|PROKKA_01350 630|PROKKA_01503
arbstring1029: 120|PROKKA_03195 196|PROKKA_03175 630|PROKKA_03374
arbstring1030: 120|PROKKA_03050 196|PROKKA_03001 630|PROKKA_03230

I want to find rows that have all of these before the "PROKKA_XXXXX":

120|
196|
630|

The following script will find them but seemingly only in the order in which they're written in the script (eg. only returns a row with 196|, 120|, 630| when I know for a fact there are rows with all three in, but in a different order):

#!/usr/bin/perl -w use strict; use warnings;

#get genes that are present in all groups  from a groups.txt

#scans through output of orthomcl to get genes that are only core open (IN,"<$ARGV[0]")  or die $!;

while (my $line = <IN>) {
#change the VS1 to match your unique phage ID add "& ($line =~m/VS11\|/)" to add more rules to match . will need 15 for 15 phage if ($line =~ m/196\|/gi && $line =~ m/120\|/gi && $line =~
m/630\|/gi)#(=~m/120\|/gi))#($line =~m/196\|/gi)

#if (/(?=.*re1)(?=.*re2)(?=.*re3)/s)

#& ($line =~m/630\|/) & ($line =~m/120\|/)   #& ($line =~m/IME1\|/) #&
#($line =~m/KBNP\|/) & ($line =~m/LUZ7\|/) & ($line =~m/PA26\|/) & ($line =~m/RLP1\|/) & ($line =~m/VC01\|/) &
#($line =~m/DSS3\|/)  & ($line =~m/EcP1\|/)  & ($line =~m/G7C\|/) & ($line =~m/JA1\|/) & ($line =~m/LIT1\|/) &
#($line =~m/N4\|/) & ($line =~m/pS6\|/) & ($line =~m/RPP1\|/) & ($line =~m/VBP3\|/) & ($line =~m/VBP4\|/) &
#($line =~m/058\|/)  &  ($line =~m/076\|/)  &  ($line =~m/JWA\|/)  &  ($line =~m/JWD\|/) & ($line =~m/PRES\|/)    { print $line ; } }

Any help with this would be brilliant as I've looked around a fair bit already...

like image 379
James Kerwin Avatar asked Jan 17 '26 09:01

James Kerwin


1 Answers

I would propose using a look-ahead:

^
(?=.*120\|PROKKA_\d+)
(?=.*196\|PROKKA_\d+)
(?=.*630\|PROKKA_\d+)
.*

regex101.com demo

(this is broken across multiple lines for readability only). Starting at the beginning of each line, look ahead for all 3 of your criteria: 120, 196, and 630. If they are found, the .* will match that line.

like image 141
OnlineCop Avatar answered Jan 20 '26 02:01

OnlineCop



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!