@secventa = ( 'gtgtttctctctaattctctctaagttttt', "atgaggaaaagtc\ncaggtctgtctgactgtct\nttgggcctggatcctccttctgagcac", 'ctgactggaagaagctatggacagccgtcattacaagatgaacttaaagacaataccact', 'gtcttcaccaggattttggacagactcctagatggttatgacaatcgcctgagaccagga', 'ttgggagagcgtgtaaccgaagtgaagactgatatcttcgtcaccagtttcggacccgtt', 'tcagaccatgatatggaatatacaatagatgtatttttccgtcaaagctggaaggatgaa', 'aggttaaaatttaaaggacctatgacagtcctccggttaaataacctaatggcaagtaaa', 'atctggactccggacacatttttccacaatggaaagaagtcagtggcccacaacatgacc', 'atgcccaacaaactcctgcggatcacagaggatggcaccttgctgtacaccatgaggctg', 'acagtgagagctgaatgtccgatgcatttggaggacttccctatggatgcccatgcttgc', 'ccactaaaatttggaagttatgcttatacaagagcagaagttgtttatgaatggaccaga', 'gagccagcacgctcagtggttgtagcagaagatggatcacgtctaaaccagtatgacctt', 'cttggacaaacagtagactctggaattgtccagtcaagtacaggagaatatgttgttatg' ); print "@secventa"; print "\n\n"; $index = $#secventa; $componente = @secventa; $pattern = 0; # în acest punct nu există niciun pattern identificat. print "\t Au fost identificate $componente secvente distincte\n"; print "\t Introduceti o cheie REGEX pentru selectie: "; $cheie = ; chomp($cheie); $j = 0; for ($i=0; $i <= $index; $i++){ if ( $secventa[$i] =~ /$cheie/){ $pozitie_inceput = $-[0]; $pozitie_sfarsit = $+[0]; $pattern = 1; print "\n"; print "S-a identificat secventa: $secventa[$i]\n"; print "S-a identificat pattern-ul: $&\n"; #push(@match, $&); # aceasta variabilă păstrează rezultatele match-urilor print "Sirul anterior : $`\n"; print "Sirul posterior: $'\n"; print "Pozitia de inceput a match-ului: $pozitie_inceput\n"; print "Pozitia de sfarsit a match-ului: $pozitie_sfarsit\n"; print "-" x 60,"\n"; } } print "\n\t Nu s-a identificat niciun pattern cu aceasta cheie: $cheie\n" if ($pattern == 0); #print 'Sirurile identificate si pastrate in variabila @match sunt urmatoarele:',"\n" if ($pattern == 1); #print "@match" if ($pattern == 1); __END__ REGEX / REGEXP - REGULAR EXPRESSIONS https://perldoc.perl.org/5.32.1/perlretut • OPERATOR =~ se potrivește !~ nu se potrivește • SINTAXĂ m/expresie/ Match Regular Expression s/expresie/substitutie/ Substitute Regular Expression tr/expresie/traducere/ Transliterate Regular Expression Ex: reverse complement of a DNA string my $revcomp = reverse $origin_seq; $revcomp =~ tr/ATGCatgc/TACGtacg/; print $revcomp; • METACARACTERE (caractere functionale) + {} ^ * \ | [] $ ? . () - + 1 sau mai multe apariții ale caracterului/expresiei situate înaintea acestuia. {n} Exact n apariții ale caracterului/expresiei situate înaintea acestuia. {n,} n sau mai multe apariții ale caracterului/expresiei situate înaintea acestuia. {n,m} Cel puțin n și cel mult m apariții ale caracterului/expresiei situate înaintea acestuia. Dacă n=0 atunci caracterul respectiv lipsește. () Delimitează un grup. În parantezele [] și {} își pierde prop. de metacaracter. . Oricare unic caracter cu excepția newline. Cu modificatorul m permite și newline. [] Oricare dintre caracterele descrise în interiorul parantezelor. [^] Oricare dintre caracterele care nu sunt descrise în interiorul parantezelor, doar dacă este la începutul expresiei, altfel își pierde prop. de metacaracter. | a|b se potrivește cu întreaga expresia a sau cu întreaga expresia b. ^ Semnifică începutul unui șir dacă nu se află în interiorul []. Comportamentul poate fi influențat de prezența modificatorului m (PCRE: multiline). În această situație începutul unui șir este considerat după fiecare \n (new line). $ Semnifică sfârșitul unui șir. Comportamentul poate fi influențat de prezența modificatorului m (PCRE: multiline). În această situație sfârșitul unui șir este considerat înainte de fiecare \n (new line). - Semnifică un interval numai în interiorul [] și numai dacă poziția acestuia poate forma un interval valid. Ex: [a-f]. Atenție la [a-f-i] sau [A-C-F-T]A-B. ? 0 sau 1 apariții ale caracterului/expresiei situate înaintea acestuia. * 0 sau mai multe apariții ale caracterului/expresiei situate înaintea acestuia. \ ESC - Anulează proprietatea de metacaracter a caracterului situat după el. METACARACTERE care își pierd proprietatea în interiorul []. Simbolul ! pus în dreptul lor atrage atenția că semnificația este dependentă de poziția metacaracterului în cadrul șirului ce formează expresia. () {} [] . - ^ + $ * ? + ! ! ! • MODIFICATORI i Makes the match case insensitive (PCRE: case insensitive) g Globally finds all matches. (PCRE: global) c Does not reset the position on a failed match. o Only compiles the pattern once. This is an efficiency thing. s Allows use of . to match a newline character. (PCRE: single line, dotall) m Specifies that if the string has newline or carriage return characters, the ^ and $ operators will now match against a newline boundary, instead of a string boundary. (PCRE: multiline) x Allows you to use white space in the expression for clarity. (PCRE: extended) xx Allows you to use white space in the expression for clarity. Similar to x • VARIABILE speciale utilizate în operatii de "matching" $& se initializeaza cu valoarea match-ului. $` se initializeaza cu sirul situat anterior match-ului. $' se initializeaza cu sirul situat posterior match-ului. $1-$n se initializeaza cu sirul/șirurile ce se potrivește/potrivesc cu un grup/grupri. @- și @+ La indexul $-[0] întodeauna va fi păstrată poziția de început a întregului match. La următorii indecși $-[1], $-[2] ... variabila primește, în funcție de situație, poziția de început a match-urilor pe care le-a făcut fiecare grup. Similar pentru $+[0] va fi păstrată poziția de sfârșit a întregului match respectiv a grupurilor. • PRESCURTARI și ECHIVALENȚE (ANCHORS) (acolo unde există o echivalență este explicitată expresia cu care face match) /\d/ - echiv. /[0-9]/ /\d+/ - echiv. /[0-9]+/ /\D/ - echiv. /[^\d]/ sau /[^0-9]/ /\D+/ - echiv. /[^\d]+/ sau /[^0-9]+/ /\w/ - echiv. /[0-9a-zA-Z_]/ /\w+/ - echiv. /[0-9a-zA-Z_]+/ /\W/ - echiv. /[^0-9a-zA-Z_]/ /\W+/ - echiv. /[^0-9a-zA-Z_]+/ /\s/ - echiv. /[ \t\r\n\f]/ /\S/ - echiv. /[^\s]/ sau /[^ \t\r\n\f]/ /\G/ - It stops matching if the mechanism failed in a global context and matches at the point where the previous /g match left off. It is closely associated with the /g modifier. It allows us to easily do context-sensitive matching. /\A/ - Matches the beginning of string. /\Z/ - Matches the end of string. These two tokens, \A and \Z, never match at line breaks. This is true in all regex flavors even when you turn on multiline mode. Only in Python, \Z matches before the final line break (new line). /\z/ - Matches end of string similar to \Z. Only in Python if you want a match at the absolute very end of the string, use \z (lowercase z) instead of uppercase Z. /\b/ - Matches word boundaries position. (in some flavors only when it is outside brackets). between a word character and non-word charcater /[^0-9a-zA-Z_]/ or position (start/end of string) Matches backspace (0x08) when inside brackets. /\B/ - Matches non-word boundaries. /\t/ - Matches tabs. /\n/ - Matches newlines. /\r/ - Matches carriage returns. /\f/ - Matches form feeds (page breaks). (!) A word boundary (\b) is a zero width match that can match: - between a word character (\w) and a non-word character (\W). - between a word character and the start or end of the string. The definition of \w is [A-Za-z0-9_] and \W is anything else [^0-9a-zA-Z_]. The negated version of \b, written \B, is a zero width match where the above does not hold. Therefore it can match: - between two word characters. - between two non-word characters. - between a non-word character and the start or end of the string. - The empty string. For example if the string is "Hello, world!" then \b matches in the following places: H e l l o , w o r l d ! ↑ ↑ ↑ ↑ and \B matches those places where \b doesn't match: H e l l o , w o r l d ! ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ Deci, prescurtările \b și \B nu trebuie considerate un substitut pentru caracterele cu care se potrivesc. De ex: șirul 'acct!gtgg,ttagg' se potrivește cu /\bgtgg\b/ dar nu se potrivește cu /acct\bgtgg\b/, de aceea \b nu trebuie confundat niciodată cu un substituient al caracterelor [^0-9a-zA-Z_], el doar evidențiază că șirul gtgg este identificabil doar între caractere care fac parte din subsetul [^0-9a-zA-Z_]. Pentru a se potrivi, cheia trebuie scrisă astfel: /acct.\bgtgg\b/ Aceasta se traduce: caută o secvență care începe cu cinci caractere acct. după care urmează șirul gtgg delimitat întotdeauna de caractere care aparțin [^0-9a-zA-Z_]. (!) The difference between \n (newline) and \r (carriage return) - In Unix and all Unix-like systems, \n is the code for end-of-line, \r means nothing special. As a consequence, in C and most languages that somehow copy it (even remotely), \n is the standard escape sequence for end of line (translated to/from OS-specific sequences as needed). - In old Mac systems (pre-OS X), \r was the code for end-of-line instead. - In Windows (and many old OSs), the code for end of line is 2 characters, \r\n, in this order. As a (surprising) consequence (harking back to OSs much older than Windows), \r\n is the standard line-termination for text formats on the Internet. - For electromechanical teletype-like "terminals", \r commands the carriage to go back leftwards until it hits the leftmost stop (a slow operation), \n commands the roller to roll up one line (a much faster operation). That's the reason you always have \r before \n, so that the roller can move while the carriage is still going leftwards! Wikipedia has a detailed explanation. https://en.wikipedia.org/wiki/Newline or https://en.wikipedia.org/wiki/Carriage_return - For character-mode terminals (typically emulating even-older printing ones as above), in raw mode, \r and \n act similarly (except both in terms of the cursor, as there is no carriage or roller). In practice, in the modern context of writing to a text file, you should always use \n (the underlying runtime will translate that if you're on a weird OS, e.g., Windows). The only reason to use \r is if you're writing to a character terminal (or more likely a "console window" emulating it) and want the next line you write to overwrite the last one you just wrote (sometimes used for goofy "ascii animation" effects of e.g. progress bars). This is getting pretty obsolete in a world of GUIs. • LOOKAHEAD Lookaheads do not consume any characters. It just checks if the lookahead can be matched or not: -Positive lookahead (?=expresie) The positive lookahead it tries to match the pattern in the lookahead. If it can be matched, then the regex engine proceeds with matching the rest of the pattern. If it cannot, the match is discarded. Ex: /abc(?=123)\d+/ matching abc123 abc123 abc123 abc123 a b c abc123 Tries to match 123; since is successful, the pointer remains at c. | (?=123) abc123 Match is success. Further matching of patterns (if any) would proceed from this position. | \d+ The pattern is matched completely. Returns a successfull match by the regex engine. Acest mecanism este util atunci când după descrierea expresiei lookahead urmează o altă expresie care are un înalt grad de generalitate și prin lookahead se restâng variantele care să fie considerate un match valid. În exemplul dat este vorba de un șir variabil de cifre dar, dacă se specifică ca lookahead o variantă particulară atunci dintre toate soluțiile posibile vor fi validate doar cele care sunt cuprinse în descrierea lookahead. Ex: /abc(?=.+123.+)\w+/ în acest exemplu se caută un șir care începe cu abc și se continuă cu un număr variabil de caractere alfanumerice. Introducerea expresiei lookahead (?=.+123.+) între abc\w+ restrânge soluțiile w+ la un număr variabil de caractere care trebuie obligatoriu să aibă pe undeva 123. -Negative lookahead (?!expresie) Dacă se folosește același exemplu /abc(?!.+123.+)\w+/ explicația dată mai sus este valabilă pentru cazul în care expresia lookahead restrânge soluțiile w+ la un număr variabil de caractere care trebuie obligatoriu să NU aibă niciunde 123. -Non-capturing group (?:expresie) You can use capturing groups to organize and parse an expression. A non-capturing group has the first benefit, but doesn't have the overhead of the second. You can still say a non-capturing group is optional, for example. Say you want to match numeric text, but some numbers could be written as 1st, 2nd, 3rd, 4th, ... If you want to capture the numeric part, but not the (optional) suffix you can use a non-capturing group. Ex: ([0-9]+)(?:st|nd|rd|th)? That will match numbers in the form 1, 2, 3, ... or in the form 1st, 2nd, 3rd, ... but it will only capture the numeric part.