Précédent   Forum des professionnels en informatique > Bases de données > Oracle > PL/SQL
PL/SQL Forum d'entraide sur le PL/SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 13/07/2011, 08h46   #1
Invité de passage
 
Femme
Étudiant
Inscription : juillet 2011
Messages : 4
Détails du profil
Informations personnelles :
Sexe : Femme

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juillet 2011
Messages : 4
Points : 0
Points : 0
Par défaut Split via Regexp

Bonjour a tous,

Je cherche une moyen de splitter une chaine de caractères et comme l'intitulé l'indique avec des expressions régulières.
Pour détailler tout ça, je passe en paramètre à une fonction stockée la chaine à découper ainsi qu'un délimiteur (là où la chaine doit être coupée), mon problème c'est que je ne sais pas comment utiliser les expressions dans ce sens là, vu que la chaine pourra comporter plusieurs occurrence du délimiteur et donc elle a une structure variable (on peut très bien avoir une chaine comme celle-ci : 'test01, test02' ou alors une comme ça : 'test01,test02,test03,..., testn')

Voila je ne sais pas si j'ai été suffisamment clair pour tout le monde, si il manque des informations, je suis dispo

Merci
guich62 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/07/2011, 10h40   #2
Membre expérimenté
 
Homme Mohamed Houri
Inscription : mars 2010
Messages : 286
Détails du profil
Informations personnelles :
Nom : Homme Mohamed Houri
Localisation : France

Informations forums :
Inscription : mars 2010
Messages : 286
Points : 563
Points : 563
Bonjour,

Je suis justement en train de faire ce travail chez un client. J'ai pour cela créé deux fonctions une classique et une autre utilisant regexp.
Je n'ai pas testé la seconde variante de la fonction, par contre j'ai bien testé la fonction classique et je pense que c'est elle que je vais devoir
promouvoir dans les environnements de test, d'acceptation et de production. Avant de vous proposer le code, j'ai trois remarques dont vous devriez tenir
compte:
(1) Mon message commence par le séparateur
(2) Vous n'êtes pas obligé d'utiliser un type table of varchar2(4000)
(3) desolé pour l'anglais dans le texte du code (je n'ai fait que copier coller pour aller plus vite)

Bien à vous

(1) fonction classique
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 
mhouri.world > CREATE OR REPLACE
  2  package split_text
  3  IS
  4  
  5   TYPE t_msg_array IS TABLE OF VARCHAR2(4000) INDEX BY BINARY_INTEGER;
  6  
  7    FUNCTION f_extract_message_info (piv_message IN VARCHAR2
  8                                    ,piv_delim   IN VARCHAR2)
  9       RETURN t_msg_array;
 10  
 11  END split_text;
 12  /
 
Package created.
 
mhouri.world > CREATE OR REPLACE package body split_text
  2  IS
  3  
  4  FUNCTION f_extract_message_info (piv_message IN VARCHAR2
  5                                   ,piv_delim   IN VARCHAR2)
  6     RETURN t_msg_array
  7  IS
  8     l_t_msg_array   t_msg_array;
  9     ln_pos          NUMBER          := 0;
 10     li              INTEGER         := 0;
 11     lv_str          VARCHAR2 (4000) := piv_message;
 12  
 13  BEGIN
 14     -- Get the position fo the first delimitor
 15     ln_pos := instr(lv_str,piv_delim,1,1);
 16  
 17     -- While there is still delimitors loop
 18     WHILE ( ln_pos != 0)
 19     LOOP
 20  
 21       -- Remove the first delimitor from the message
 22       lv_str := substr(lv_str,ln_pos + length(piv_delim),length(lv_str));
 23  
 24       -- Determine now the new position of the first delimitor
 25       ln_pos := instr(lv_str,piv_delim,1,1);
 26  
 27       -- Fill each information of the message in an array
 28       li := li + 1;
 29       IF ln_pos != 0
 30       THEN
 31         l_t_msg_array(li) := substr(lv_str,1, ln_pos-1);
 32       ELSE
 33         l_t_msg_array(li) := lv_str;
 34       END IF;
 35  
 36     END LOOP;
 37  
 38     -- return the array
 39      RETURN l_t_msg_array;
 40  
 41  END f_extract_message_info;
 42  
 43  
 44  END split_text;
 45  /
 
Package body created.
 
mhouri.world > SET serveroutput ON
mhouri.world > declare
  2   piv_txt            varchar2(4000);
  3   l_t_jus_msg_array  split_text.t_msg_array;
  4  
  5  BEGIN
  6  
  7   piv_txt := '#@test01#@test02#@test03';
  8  
  9   l_t_jus_msg_array     := split_text.f_extract_message_info(piv_txt,'#@');
 10  
 11   dbms_output.put_line(' item1 := '||l_t_jus_msg_array(1) );
 12   dbms_output.put_line(' item2 := '||l_t_jus_msg_array(2));
 13   dbms_output.put_line(' item3 := '||l_t_jus_msg_array(3));
 14  
 15  
 16  END;
 17  /
item1 := test01                                                                 
item2 := test02                                                                 
item3 := test03                                                                 
 
PL/SQL procedure successfully completed.
(1) fonction avec regexp (pas suffisamment testée )

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
 
mhouri.world > CREATE OR REPLACE
  2  package split_text
  3  IS
  4  
  5   TYPE t_msg_array IS TABLE OF VARCHAR2(4000) INDEX BY BINARY_INTEGER;
  6  
  7  
  8    FUNCTION f_extract_message_info_regexp (piv_message IN VARCHAR2
  9                                            ,piv_delim   IN VARCHAR2)
 10       RETURN t_msg_array;
 11  
 12  
 13  END split_text;
 14  /
 
Package created.
 
mhouri.world > CREATE OR REPLACE
  2  package body split_text
  3  IS
  4  
  5  FUNCTION f_extract_message_info_regexp (piv_message IN VARCHAR2
  6                                         ,piv_delim   IN VARCHAR2)
  7  /* ***************************************************************
  8   * Name     : f_extract_message_info                             *
  9   * Author   : Mohamed Houri                                      *
 10   * Abstract : it extracts tables fields from a payload message   *
 11   *****************************************************************/
 12     RETURN t_msg_array
 13  IS
 14     l_t_msg_array   t_msg_array;
 15     ln_pos          NUMBER          := 0;
 16     li              INTEGER         := 0;
 17     lv_str          VARCHAR2 (4000) := piv_message;
 18  
 19  BEGIN
 20     -- get the first position of the string
 21     ln_pos := INSTR (lv_str, piv_delim, 1, 1);
 22  
 23     WHILE (ln_pos != 0)
 24     LOOP
 25       -- Increment the array string counter
 26        li := li + 1;
 27  
 28       -- Create array element
 29        l_t_msg_array (li) := substr (regexp_substr (lv_str, '#@[^#@]*', 1, 1), 3);
 30  
 31       -- Remove from the original message the part of info that has been extracted
 32        lv_str := substr (lv_str, ln_pos + 1, length (lv_str));
 33  
 34        -- Determine the new position of first delimiter in the string
 35        ln_pos := instr (lv_str, piv_delim, 1, 1);
 36  
 37     END LOOP;
 38  
 39     RETURN l_t_msg_array;
 40  END f_extract_message_info_regexp;
 41  
 42  END split_text;
 43  /
 
Package body created.
 
mhouri.world > declare
  2   piv_txt            varchar2(4000);
  3   l_t_jus_msg_array  split_text.t_msg_array;
  4  
  5  BEGIN
  6  
  7   piv_txt := '#@test01#@test02#@test03';
  8  
  9   l_t_jus_msg_array     := split_text.f_extract_message_info_regexp(piv_txt,'#@');
 10  
 11   dbms_output.put_line(' item1 := '||l_t_jus_msg_array(1) );
 12   dbms_output.put_line(' item2 := '||l_t_jus_msg_array(2));
 13   dbms_output.put_line(' item3 := '||l_t_jus_msg_array(3));
 14  
 15  
 16  END;
 17  /
item1 := test01                                                                 
item2 := test02                                                                 
item3 := test03                                                                 
 
PL/SQL procedure successfully completed.
Bien Cordialement

Mohamed Houri
Mohamed.Houri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/07/2011, 10h52   #3
Invité de passage
 
Femme
Étudiant
Inscription : juillet 2011
Messages : 4
Détails du profil
Informations personnelles :
Sexe : Femme

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juillet 2011
Messages : 4
Points : 0
Points : 0
Ok, merci je vais tester ça (la partie avec des regexp) l'autre m'intéresse moins vu que je l'ai déjà faite de mon côté mais par souci d'optimisation je préfère utiliser des expressions régulières.

Je repasserai dès que j'aurai adapté ça à mon travail
guich62 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/07/2011, 11h45   #4
Invité de passage
 
Femme
Étudiant
Inscription : juillet 2011
Messages : 4
Détails du profil
Informations personnelles :
Sexe : Femme

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juillet 2011
Messages : 4
Points : 0
Points : 0
Alors voila ce que ça donne pour moi, bon ça ne remplit pas tout à fait ce que je veux faire en complet mais ça couvre une partie.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
    ln_pos := INSTR (chaine_parcour, delimiter);
    WHILE (ln_pos != 0)
      LOOP
 
        -- Create array element
         table_reg(table_reg.count + 1).nom := substr (regexp_substr (chaine_parcour,'[^' || delimiter || ']*' || delimiter, 1, 1), 0,ln_pos - 1);
 
        -- Remove from the original message the part of info that has been extracted
         chaine_parcour := substr (chaine_parcour, ln_pos + 1, length (chaine_parcour));
 
         -- Determine the new position of first delimiter in the string
         ln_pos := instr (chaine_parcour, delimiter, 1, 1);
 
      END LOOP;
 
     IF ln_pos = 0 then
 
         table_reg(table_reg.count + 1).nom := substr (regexp_substr (chaine_parcour,'[^' || delimiter || ']*$'  , 1, 1), 2);
 
     End IF;
Ma chaine à découper étant différente de la tienne, j'ai donc adapté à ma "sauce", maintenant il faut que j'ajoute une fonction qui fasse presque la même chose.
Il me faut une nouvelle fois découper une chaine mais qui sera sous cette forme : 'test01 a, test02 b, ...' en séparant au niveau de chaque espace, ce n'est pas bien compliqué puisque j'ai déjà la séparation au niveau des virgules !

Merci l'ami de m'avoir aider
guich62 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 23h57.


 
 
 
 
Partenaires

Hébergement Web