1
votes

Regex - Comment faire correspondre une séquence de 3 lettres spécifique, après un nombre donné de séquences de 3 lettres?

J'étudie la génétique, et je me demandais comment je pourrais saisir la 248ème séquence de 3 lettres de certaines données ADN, j'essaie de trouver une expression regex correspondant à cela. Le bloc de données a également des nombres au début de chaque ligne qui doivent être exclus avec des espaces, seules les lettres doivent être comptées dans la séquence. En gros, toutes les 3 lettres comptent pour une séquence, et je veux trouver la 248e séquence. Les données sont également au format chaîne.

                              atggagga gccgcagtca gatcctagcg tcgagccccc
  241 tctgagtcag gaaacatttt cagacctatg gaaactactt cctgaaaaca acgttctgtc
  301 ccccttgccg tcccaagcaa tggatgattt gatgctgtcc ccggacgata ttgaacaatg
  361 gttcactgaa gacccaggtc cagatgaagc tcccagaatg ccagaggctg ctccccccgt
  421 ggcccctgca ccagcagctc ctacaccggc ggcccctgca ccagccccct cctggcccct
  481 gtcatcttct gtcccttccc agaaaaccta ccagggcagc tacggtttcc gtctgggctt
  541 cttgcattct gggacagcca agtctgtgac ttgcacgtac tcccctgccc tcaacaagat
  601 gttttgccaa ctggccaaga cctgccctgt gcagctgtgg gttgattcca cacccccgcc
  661 cggcacccgc gtccgcgcca tggccatcta caagcagtca cagcacatga cggaggttgt
  721 gaggcgctgc ccccaccatg agcgctgctc agatagcgat ggtctggccc ctcctcagca
  781 tcttatccga gtggaaggaa atttgcgtgt ggagtatttg gatgacagaa acacttttcg
  841 acatagtgtg gtggtgccct atgagccgcc tgaggttggc tctgactgta ccaccatcca
  901 ctacaactac atgtgtaaca gttcctgcat gggcggcatg aaccggaggc ccatcctcac
  961 catcatcaca ctggaagact ccagtggtaa tctactggga cggaacagct ttgaggtgcg
 1021 tgtttgtgcc tgtcctggga gagaccggcg cacagaggaa gagaatctcc gcaagaaagg
 1081 ggagcctcac cacgagctgc ccccagggag cactaagcga gcactgccca acaacaccag
 1141 ctcctctccc cagccaaaga agaaaccact ggatggagaa tatttcaccc ttcagatccg
 1201 tgggcgtgag cgcttcgaga tgttccgaga gctgaatgag gccttggaac tcaaggatgc
 1261 ccaggctggg aaggagccag gggggagcag ggctcactcc agccacctga agtccaaaaa
 1321 gggtcagtct acctcccgcc ataaaaaact catgttcaag acagaagggc ctgactcaga
 1381 ctga

Toute aide serait fantastique! Je me tire les cheveux pour ça

Merci :)


11 commentaires

248ème séquence de 3 lettres Qu'est-ce que c'est? Quels sont ces chiffres sur la gauche?


Les nombres signifient juste combien de lettres ont été comptées depuis le début du bloc de gènes, ceci est un extrait du bloc. Ignorez simplement les chiffres :) Désolé


donc toutes les 3 lettres sont comptées comme une séquence de 3 lettres, donc je veux trouver la 248e séquence de 3 lettres, si vous me comprenez?


Comment recevez-vous cela au format code? pouvez vous partager? Est-ce une chaîne ou un tableau comme clé (chiffres) avec ces chaînes sur la droite comme valeur? Quelle est la réponse à la 248ème séquence de 3 lettres ?


Donc c'est une chaîne pour le moment malheureusement, je ne connais pas la réponse qui est ennuyeuse, et j'essaye de ne pas avoir à compter 248 groupes de trois lettres, car je dois le faire plusieurs fois


Supprimez peut-être les premiers chiffres et supprimez tous les espaces. Répétez ensuite 247 fois une séquence de 3 caractères et capturez dans le groupe 1 la 248e fois ^ (?:. {3}) {247} (. {3}) regex101.com/r/Z3YCIj/1


S'il s'agit simplement d'une chaîne continue sans espaces et sans nombre de caractères, utilisez simplement substr ($ sequence, (247 * 3) -1, 3) ou quelque chose comme ça.


Ou incluez la correspondance des caractères d'espacement (?: (?: [Agct] \ s *) {3}) {247} ([agct] {3}) regex101.com/r/2ZXNgp/1


En utilisant le preg_match de PHP, vous pouvez faire correspondre tous les groupes en compensant les nombres et les espaces 248 fois, puis choisir la valeur capturée; voir regex101.com/r/51dQEh/1 . Ou regex101.com/r/I8fpqF/1 si vous ne souhaitez pas capturer.


Ce genre de problème est à quoi sert RE, et maintenant que l'OP l'a édité, il doit être ouvert dès que possible, imo.


3v4l.org/aqDYm


3 Réponses :


0
votes

Une approche consiste à faire correspondre n-1 occurrences du modèle, puis à capturer l'occurrence suivante.

$pattern = '/
 (?(DEFINE)(?<sequence>(?:[a-z][^a-z]*){3})) # define a pattern for a 3 letter sequence
 (?&sequence){247} # consume 247 occurrences 
 (?<match>(?&sequence)) # match 248th occurrence
/x';

if (preg_match($pattern, $data, $matches)) {
  var_dump(preg_replace('/[^a-z]+/', '', $matches['match']));
}


0 commentaires

1
votes

Une façon de comparer directement avec votre bloc de données serait de compenser les nombres et les espaces tout en faisant correspondre et en capturant toutes les séquences de trois caractères de la classe [acgt] pour le nombre de fois que vous exiger. Seule la capture la plus récente sera disponible. Exemple à utiliser avec preg_match :

array(1) { [0]=> array(1) { [0]=> string(3) "cgg" } }

Voir démo regex .

Dans le code:

$re = '/\A(?:(?:[\s\d]*[acgt]){3}){247}\K(?:[\s\d]*[acgt]){3}/m';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
var_dump($matches);

Sortie (simplifiée):

/\A(?:(?:[\s\d]*[acgt]){3}){247}\K(?:[\s\d]*[acgt]){3}/m

OU Une variante de cette expression si vous souhaitez faire correspondre directement la cible uniquement:

array(1) { [0]=> array(2) { [0]=> string(...) " atgg...cgg" [1]=> string(3) "cgg" } }

\ K permet au moteur de se souvenir de la position du dernier match, mais de jeter le contenu de ce match jusqu'à ce point. Voir démo regex .

Dans le code:

$re = '/\A(?:((?:[\s\d]*[acgt]){3})){248}/m';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
var_dump($matches);

Résultat:

/\A(?:((?:[\s\d]*[acgt]){3})){248}/m

Heureux de voir cette question rouverte. :)


0 commentaires

0
votes

En utilisant JavaScript, vous pouvez supprimer les espaces et les chiffres avec string.replace () , puis saisir la nième séquence de 3 lettres, par exemple avec string.substring():

<?php

$data = <<<DNA
                              atggagga gccgcagtca gatcctagcg tcgagccccc
  241 tctgagtcag gaaacatttt cagacctatg gaaactactt cctgaaaaca acgttctgtc
  301 ccccttgccg tcccaagcaa tggatgattt gatgctgtcc ccggacgata ttgaacaatg
  ...
DNA;

$sequences = preg_replace('/\s|\d/', '', $data);
$sequences = str_split($sequences, 3);

echo $sequences[0] . PHP_EOL;
echo $sequences[1] . PHP_EOL;
echo $sequences[247];

En utilisant PHP, vous pouvez supprimer les espaces et les chiffres avec preg_replace () , puis diviser la chaîne en un tableau de chaînes de 3 lettres avec str_split():

const data = `
                              atggagga gccgcagtca gatcctagcg tcgagccccc
  241 tctgagtcag gaaacatttt cagacctatg gaaactactt cctgaaaaca acgttctgtc
  301 ccccttgccg tcccaagcaa tggatgattt gatgctgtcc ccggacgata ttgaacaatg
  361 gttcactgaa gacccaggtc cagatgaagc tcccagaatg ccagaggctg ctccccccgt
  421 ggcccctgca ccagcagctc ctacaccggc ggcccctgca ccagccccct cctggcccct
  481 gtcatcttct gtcccttccc agaaaaccta ccagggcagc tacggtttcc gtctgggctt
  541 cttgcattct gggacagcca agtctgtgac ttgcacgtac tcccctgccc tcaacaagat
  601 gttttgccaa ctggccaaga cctgccctgt gcagctgtgg gttgattcca cacccccgcc
  661 cggcacccgc gtccgcgcca tggccatcta caagcagtca cagcacatga cggaggttgt
  721 gaggcgctgc ccccaccatg agcgctgctc agatagcgat ggtctggccc ctcctcagca
  781 tcttatccga gtggaaggaa atttgcgtgt ggagtatttg gatgacagaa acacttttcg
  841 acatagtgtg gtggtgccct atgagccgcc tgaggttggc tctgactgta ccaccatcca
  901 ctacaactac atgtgtaaca gttcctgcat gggcggcatg aaccggaggc ccatcctcac
  961 catcatcaca ctggaagact ccagtggtaa tctactggga cggaacagct ttgaggtgcg
 1021 tgtttgtgcc tgtcctggga gagaccggcg cacagaggaa gagaatctcc gcaagaaagg
 1081 ggagcctcac cacgagctgc ccccagggag cactaagcga gcactgccca acaacaccag
 1141 ctcctctccc cagccaaaga agaaaccact ggatggagaa tatttcaccc ttcagatccg
 1201 tgggcgtgag cgcttcgaga tgttccgaga gctgaatgag gccttggaac tcaaggatgc
 1261 ccaggctggg aaggagccag gggggagcag ggctcactcc agccacctga agtccaaaaa
 1321 gggtcagtct acctcccgcc ataaaaaact catgttcaag acagaagggc ctgactcaga
 1381 ctga
`

function getNthSequence(n) {
  const sequenceLength = 3
  const startIndex = (n - 1) * sequenceLength

  return data
    .replace(/\s|\d/g, '')
    .substring(startIndex, startIndex + sequenceLength)
}

console.log(getNthSequence(1))
console.log(getNthSequence(2))
console.log(getNthSequence(248))

Voir https://3v4l.org/9mpcE pour une démonstration.


Addendum:

Je viens de remarquer que vous semblez rechercher spécifiquement une solution regex. Cependant, comme on peut le voir dans ma réponse, il n'est pas nécessaire d'utiliser l'expression régulière pour faire correspondre / obtenir la nième séquence de 3 lettres, et je dirais que l'utilisation de string.substring () code> (en JS) ou str_split () (en PHP) est plus propre et plus lisible que l'utilisation d'un modèle regex complexe. Néanmoins, regex est un choix valide pour supprimer les espaces et les nombres de la chaîne de données.


0 commentaires