{"id":227,"date":"2009-03-08T08:53:53","date_gmt":"2009-03-08T08:53:53","guid":{"rendered":"http:\/\/blog.milamberspace.net\/?p=227"},"modified":"2011-12-28T17:22:52","modified_gmt":"2011-12-28T17:22:52","slug":"jmeter-trouver-le-bon-element-dans-une-liste-avec-les-expressions-regulieres-et-en-mode-ligne-unique","status":"publish","type":"post","link":"https:\/\/blog.milamberspace.net\/index.php\/2009\/03\/08\/jmeter-trouver-le-bon-element-dans-une-liste-avec-les-expressions-regulieres-et-en-mode-ligne-unique-227.html","title":{"rendered":"JMeter : Trouver le bon \u00e9l\u00e9ment dans une liste avec les expressions r\u00e9guli\u00e8res et en mode ligne unique"},"content":{"rendered":"<p>Voici un billet pour parler des expressions r\u00e9guli\u00e8res (regexp) avec JMeter. L&rsquo;\u00e9l\u00e9ment Extracteur d&rsquo;expressions r\u00e9guli\u00e8res est tr\u00e8s utile dans les sc\u00e9nario JMeter pour extraire des donn\u00e9es de la r\u00e9ponse re\u00e7ues suite \u00e0 une requ\u00eate. Par contre, il n&rsquo;est pas toujours facile d&rsquo;avoir (de trouver) la bonne regexp&#8230;<\/p>\n<p>J&rsquo;ai mis quelques heures pour trouver cette regexp qui \u00e9tait n\u00e9cessaire pour la pr\u00e9paration d&rsquo;un sc\u00e9nario de test de charges JMeter. J&rsquo;ai m\u00eame adapt\u00e9 un petit programme Java\/Swing testeur de regexp style Java pour qu&rsquo;il devienne un programme testeur de regexp Jakarta ORO, celui du JMeter, ceci afin de tester plus vite les diff\u00e9rentes regexp.<\/p>\n<p>Commen\u00e7ons, soit le texte de r\u00e9ponse d&rsquo;une requ\u00eate HTTP (utilisant en fait SOAP\/XML-RPC) suivant :<\/p>\n<pre>&amp;lt;ClientBean&gt;\r\n&amp;lt;id&gt;765432&amp;lt;\/id&gt;\r\n&amp;lt;code&gt;1.87665308&amp;lt;\/code&gt;\r\n&amp;lt;nom&gt;JAMES BOND&amp;lt;\/nom&gt;\r\n&amp;lt;statutNumAppel&gt;Inactif&amp;lt;\/statutNumAppel&gt;\r\n&amp;lt;\/ClientBean&gt;\r\n&amp;lt;ClientBean&gt;\r\n&amp;lt;id&gt;765432&amp;lt;\/id&gt;\r\n&amp;lt;code&gt;1.33333333&amp;lt;\/code&gt;\r\n&amp;lt;nom&gt;LARGO WINCH&amp;lt;\/nom&gt;\r\n&amp;lt;statutNumAppel&gt;Inactif&amp;lt;\/statutNumAppel&gt;\r\n&amp;lt;\/ClientBean&gt;\r\n&amp;lt;ClientBean&gt;\r\n&amp;lt;id&gt;765432&amp;lt;\/id&gt;\r\n&amp;lt;code&gt;1.87999999&amp;lt;\/code&gt;\r\n&amp;lt;nom&gt;BENGAMIN GATES&amp;lt;\/nom&gt;\r\n&amp;lt;statutNumAppel&gt;Actif&amp;lt;\/statutNumAppel&gt;\r\n&amp;lt;\/ClientBean&gt;\r\n&amp;lt;ClientBean&gt;\r\n&amp;lt;id&gt;765432&amp;lt;\/id&gt;\r\n&amp;lt;code&gt;1.23334444&amp;lt;\/code&gt;\r\n&amp;lt;nom&gt;EMMA PEAL&amp;lt;\/nom&gt;\r\n&amp;lt;statutNumAppel&gt;Inactif&amp;lt;\/statutNumAppel&gt;\r\n&amp;lt;\/ClientBean&gt;<\/pre>\n<p><em>Cette liste est dynamique (on n&rsquo;a pas toujours 4 \u00e9l\u00e9ments, celui ayant le statut d&rsquo;actif n&rsquo;est pas toujours \u00e0 cette position (ici 3\u00e8me) et les valeurs bien entendues changent pour chaque requ\u00eate du test).<\/em><\/p>\n<p>Comment faire pour extraire le code \u00ab 1.87999999 \u00bb correspondant au m\u00eame ID 765432 pour chaque \u00e9l\u00e9ment de cette liste, et qui est celui \u00ab Actif \u00bb ? Le tout avec une expression r\u00e9guli\u00e8re JMeter ?<!--more--><\/p>\n<p>Avant de commencer, je rappelle que l&rsquo;analyseur d&rsquo;expressions r\u00e9guli\u00e8res de JMeter est <a href=\"http:\/\/jakarta.apache.org\/oro\/\" target=\"_blank\">Jakarto ORO<\/a>. Celui-ci fourni un moteur qui reproduit le comportement du moteur d&rsquo;expressions r\u00e9guli\u00e8res de Perl v5.003. On peut donc se r\u00e9f\u00e9rer \u00e0 la <a title=\"Documentation Perl\" href=\"http:\/\/perldoc.perl.org\/perl.html\" target=\"_blank\">documentation de Perl<\/a> pour comprendre les expressions r\u00e9guli\u00e8res.<\/p>\n<p><strong><span style=\"color: #003366;\"><em>NB. Depuis la version 2.4 de JMeter, le r\u00e9cepteur Arbre de r\u00e9sultats propose une vue Testeur de RegExp qui permet de tester une expression r\u00e9guli\u00e8re directement sur la r\u00e9ponse de la requ\u00eate re\u00e7ue.<\/em><\/span><\/strong><\/p>\n<p>Pour revenir \u00e0 notre question. Tout d&rsquo;abord, il faut passer en <strong>mode ligne unique<\/strong> au niveau de l&rsquo;analyseur de regexp, pour cela, on utilise un \u00ab modificateur \u00bb Perl. Un <em>modifier<\/em> sert \u00e0 changer le comportement de l&rsquo;analyseur.<\/p>\n<p>Le modificateur \u00ab ligne unique\u00bb est \u00e0 ajouter dans l&rsquo;expression r\u00e9guli\u00e8re. Aussi, on place en d\u00e9but de la regexp, la cha\u00eene suivante : \u00ab <strong>(?s)<\/strong> \u00bb<\/p>\n<p>Maintenant, avec le<span style=\"color: #ff00ff;\"> <strong>(?s)<\/strong><\/span>, les caract\u00e8res de fin de ligne \u00ab <strong>\\n<\/strong> \u00bb sont consid\u00e9r\u00e9s comme n&rsquo;importe quel caract\u00e8re, (symbolis\u00e9 par le point \u00ab . \u00bb dans une regexp), ce qui signifie que le texte \u00e0 analyser devient un grand texte d&rsquo;une seule ligne du point de vue de l&rsquo;analyseur.<\/p>\n<p>Ensuite la grosse difficult\u00e9 est que l&rsquo;on veut le code pour l&rsquo;\u00e9l\u00e9ment qui en <em>statutNumAppel<\/em> \u00e0 <em>Actif<\/em>. La premi\u00e8re id\u00e9e de regexp est :<\/p>\n<pre><strong><span style=\"color: #ff00ff;\">(?s)<\/span><span style=\"color: #008000;\">code&gt;(.+?)&amp;lt;\/code<\/span><span style=\"color: #0000ff;\">.+?statutNumAppel&gt;Actif<\/span><\/strong><\/pre>\n<p>Malheureusement, cela ne fonctionnera pas, car on se trouve toujours avec le premier &lsquo;code&rsquo; (ici 1.87665308). Pourquoi, car le deuxi\u00e8me \u00ab <strong>.+? <\/strong>\u00bb va englober tous les caract\u00e8res entre la premi\u00e8re occurrence du code et le statut Actif.<\/p>\n<p>Pour indiquer \u00e0 l&rsquo;analyseur de regexp que l&rsquo;on veut \u00ab <em>le code qui est coll\u00e9 \u00e0 l&rsquo;Actif<\/em> \u00bb, il faut \u00eatre un peu plus explicite. Cette regexp sera la bonne <em>(apr\u00e8s une bonne cinquantaine de tentative et relecture de la documentation des regexp)<\/em> :<\/p>\n<pre><strong><span style=\"color: #ff00ff;\">(?s)<\/span><span style=\"color: #008000;\">(?:&gt;.+?&amp;lt;\/code.+)<\/span><span style=\"color: #ff9900;\">{0,}<\/span><span style=\"color: #0000ff;\">&gt;(.+?)&amp;lt;\/code.+?<\/span><span style=\"color: #800080;\">Actif<\/span><\/strong><\/pre>\n<p>Celle-ci indique :<\/p>\n<ul>\n<li>Avec le <span style=\"color: #008000;\"><strong>(?:&gt;.+?&amp;lt;\/code.+)<\/strong><\/span> on indique un groupement (gr\u00e2ce aux parenth\u00e8ses) que l&rsquo;on ne veut pas enregistrer dans une variable <em>$x$<\/em> \u00e0 cause du <strong>?:<\/strong> situ\u00e9 au d\u00e9but.<\/li>\n<li>Avec<span style=\"color: #ff6600;\"><strong> {0,}<\/strong><\/span> on indique que l&rsquo;on veut ce groupement <span style=\"color: #008000;\"><strong>(?:&gt;.+?&amp;lt;\/code.+)<\/strong><\/span> de 0 \u00e0 n fois, l&rsquo;analyseur doit donc rechercher <strong>toutes<\/strong> les occurrences du code.<\/li>\n<li>Avec le deuxi\u00e8me <span style=\"color: #0000ff;\"><strong>&gt;(.+?)&amp;lt;\/code.+<\/strong><\/span> on &lsquo;<em>surprend<\/em>&lsquo; l&rsquo;analyseur pour lui dire que finalement on ne veut pas toutes les occurrences, mais<strong> les occurrences N \u2013 1<\/strong> dans le groupement pr\u00e9c\u00e9dent<\/li>\n<li>Avec le <span style=\"color: #800080;\"><strong>Actif<\/strong><\/span> on lui pr\u00e9cise que l&rsquo;on veut l&rsquo;<strong>occurrence N<\/strong> du &lsquo;code&rsquo; suivie par le statut <em>Actif<\/em>.<\/li>\n<\/ul>\n<p>Et voil\u00e0, c&rsquo;est &lsquo;simple&rsquo;, une fois que l&rsquo;on a trouv\u00e9&#8230; \ud83d\ude09<\/p>\n<p>En compl\u00e9ment,<\/p>\n<p>a) JMeter est par d\u00e9faut en mode multiligne (pour l&rsquo;avoir <em>explicitement<\/em>, il faut \u00ab<strong> (?m)<\/strong> en d\u00e9but d&rsquo;expression r\u00e9guli\u00e8re.<\/p>\n<p>b) En mode ligne unique \u00ab<strong> (?s)<\/strong> \u00bb, le d\u00e9but de la ligne est repr\u00e9sent\u00e9e par l&rsquo;accent circonflexe \u00ab <strong>^<\/strong> \u00bb, et la fin de ligne par le signe dollar \u00ab <strong>$<\/strong> \u00bb<\/p>\n<p><span style=\"text-decoration: underline;\">Pour en savoir plus sur les expressions r\u00e9guli\u00e8res au niveau JMeter :<\/span><\/p>\n<ul>\n<li><a href=\"http:\/\/jakarta.apache.org\/jmeter\/usermanual\/regular_expressions.html\" target=\"_self\">Page d&rsquo;aide sur les regexp au niveau JMeter<\/a><\/li>\n<li>La <a href=\"http:\/\/perldoc.perl.org\/perlreref.html\" target=\"_self\">page des regexp en Perl<\/a>, c&rsquo;est la m\u00eame syntaxe dans JMeter<\/li>\n<\/ul>\n<p><span style=\"text-decoration: underline;\">Pour tester ses regexp en dehors de JMeter :<\/span><\/p>\n<ul>\n<li><a title=\"ORO\" href=\"http:\/\/jakarta.apache.org\/oro\/demo.html\" target=\"_self\">Demonstrateur ORO<\/a> sur le site de Jakarta ORO<\/li>\n<\/ul>\n<p>.\/<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Voici un billet pour parler des expressions r\u00e9guli\u00e8res (regexp) avec JMeter. L&rsquo;\u00e9l\u00e9ment Extracteur d&rsquo;expressions r\u00e9guli\u00e8res est tr\u00e8s utile dans les sc\u00e9nario JMeter pour extraire des donn\u00e9es de la r\u00e9ponse re\u00e7ues suite \u00e0 une requ\u00eate. Par contre, il n&rsquo;est pas toujours facile d&rsquo;avoir (de trouver) la bonne regexp&#8230; J&rsquo;ai mis quelques heures pour trouver cette regexp &hellip; <a href=\"https:\/\/blog.milamberspace.net\/index.php\/2009\/03\/08\/jmeter-trouver-le-bon-element-dans-une-liste-avec-les-expressions-regulieres-et-en-mode-ligne-unique-227.html\" class=\"more-link\">Continuer la lecture de <span class=\"screen-reader-text\">JMeter : Trouver le bon \u00e9l\u00e9ment dans une liste avec les expressions r\u00e9guli\u00e8res et en mode ligne unique<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[32,33,34],"tags":[166,330,165,164],"class_list":["post-227","post","type-post","status-publish","format-standard","hentry","category-apache","category-jmeter","category-tests-de-charges","tag-fonctionnel","tag-jmeter","tag-oro","tag-regexp"],"_links":{"self":[{"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/posts\/227","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/comments?post=227"}],"version-history":[{"count":14,"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/posts\/227\/revisions"}],"predecessor-version":[{"id":1032,"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/posts\/227\/revisions\/1032"}],"wp:attachment":[{"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/media?parent=227"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/categories?post=227"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/tags?post=227"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}