banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

Rencontres QGIS 2025

L'appel à participation est ouvert jusqu'au 19 janvier 2025!

#1 Sun 10 September 2023 14:21

Pascal1968
Participant occasionnel
Date d'inscription: 21 Aug 2023
Messages: 10

QGIS: Extraction partielle chaine de caracteres

Bonjour à toutes et tous,

J'ai un petit souci d'extraction partielle d'une chaîne de caractères d'un champ pour remplir un autre champ.
Je sais qu'il y déjà quantité de sujet du même style, mais l'expression que j'utilise fonctionne parfaitement sauf pour un cas en particulier.
Si quelqu'un sait me dépanner ... ?

Soit une couche avec un champ "Fullname" comprenant des valeurs de type :
Abies concolor => Genus + Species
Acer campestre _'Elsrijk' => Genus + Species + Cultivar
Carpinus betulus _'Albert Beeckman' => Genus + Species + Cultivar (cultivar en deux mots)
Ilex  _'Nellie R. Stevens' => Genus + Cultivar
Populus (x) canadensis => Genus + Species (mais avec "(+)" devant le nom d'espèce)
Salix (x) sepulcralis _'Chrysocoma' => Genus + Species (mais avec "(+)" devant le nom d'espèce) + Cultivar

Je souhaite remplir automatiquement un champ "Genus", un champ "Species" et un champ "Cultivar" sur base de "Fullname".
"Genus" est le premier mot de "Fullname".
"Species" est le second mot sans quotes de "Fullname" lorsque ce deuxième mot existe.
"Cultivar est le second ou troisième mot de "Fullname" et est toujours entre deux quotes.

Pour "Genus", en valeur par défaut, je mets :

Code:

array_get (string_to_array ("Fullname",' '), 0)

Pour "Cultivar", en valeur par défaut, je mets :

Code:

array_get (string_to_array ("Fullname",'_'), 1)

Les deux expressions fonctionnent à marveille.

Le problème est pour le champ "Species".
En valeur par défaut, pour résoudre tous les différents cas, je mets:

Code:

CASE
WHEN length("Fullname")-length(replace("Fullname", '(x)', '')) = 3
THEN 'x '||array_get (string_to_array ("Fullname",'(x)'), 1)
ELSE
array_get (string_to_array ("Fullname",' '), 1)
END

Cela fonctionne dans tous les cas sauf un: les valeur du type Salix (x) sepulcralis _'Chrysocoma' qui renvoient "x sepulcralis _'Chrysocoma'".
Il y a donc la partie ( _'Chrysocoma') en trop.
Voir capture d'écran : [img]https://imagizer.imageshack.com/img923/2386/5YvlLf.jpg[/img]

J'ai essayé de comprendre l'expression regexp_substr, mais sans succès
Elle me semble pourtant être adaptée à ce que je souhaite faire : extraire une partie d'une chaîne de caractères, toujours comprise entre les deux mêmes caractères.
Début = la parenthèse fermée.
Fin = le underscroll (en réalité, l'espace avant le underscroll).

Une âme charitable pourrait-elle me mettre sur la bonne piste ?
D'avance merci !

Dernière modification par SANTANNA (Sun 10 September 2023 19:57)


Fichier(s) joint(s) :
Pour accéder aux fichiers vous devez vous inscrire.

Hors ligne

 

#2 Sun 10 September 2023 23:09

p.jeremie
Participant assidu
Lieu: Valence
Date d'inscription: 10 Sep 2017
Messages: 427

Re: QGIS: Extraction partielle chaine de caracteres

J'ai essayé quelque chose qui pourrait t'aller, avec regexp_matches.

Code:

regexp_matches(  replace(fullname,'(x) ',''),'^([a-zA-Z0-9_]+) ([a-zA-Z0-9_]*) ?(_.+)*$')

Permet de récupérer une liste de toutes les chaînes repérées par l'expression rationnelle.

J'ai remplacé le (x) et l'espace qui le suit par une chaine vide pour ne pas à avoir à le gérer dans l'expression rationnelle. J'espère que j'ai bien compris et que tu ne souhaitais pas le récupérer dans tes champs ?

L'expression rationnelle récupère 3 groupes (ce sont les parenthèses qui servent à faire les groupes) qu'on récupère dans une liste :
- genus = le premier groupe de lettres ou chiffres [a-zA-Z0-9_]+ le ^ servant à indiquer que c'est le début de la ligne et le + pour indiquer 1 à n répétitions de lettres ou chiffres
- species = le deuxième groupe de lettres ou chiffres (mais peut aussi être vide, c'est à ça que sert le * : 0 à n répétitions de lettres ou chiffres)
- cultivar = après une deuxième espace optionnelle (?) on a à la suite un underscore suivi de n'importe quel caractère (.) répété entre 1 et n fois (+). Cet ensemble peut être présent 0 à n fois (*) et enfin fin de ligne ($)

Ensuite, pour récupérer le bon groupe, tu peux utiliser le array_get() :
Pour genus

Code:

array_get(regexp_matches(  replace(fullname,'(x) ',''),'^([a-zA-Z0-9_]+) ([a-zA-Z0-9_]*) ?(_.+)*$'),0)

Pour species

Code:

array_get(regexp_matches(  replace(fullname,'(x) ',''),'^([a-zA-Z0-9_]+) ([a-zA-Z0-9_]*) ?(_.+)*$'),1)

Pour cultivar

Code:

 regexp_replace(array_get(regexp_matches(  replace(fullname,'(x) ',''),'^([a-zA-Z0-9_]+) ([a-zA-Z0-9_]*) ?(_.+)*$'),2),'[_'']','')

J'ai ajouté un regexp_replace qui remplace les underscore et les quotes par une chaîne vide.

En espérant que ça réponde à ta problématique.

P.S. : si tu veux mieux comprendre les expressions rationnelles, un bon site est https://regex101.com/
Par exemple avec l'expression que je t'ai donnée et tes valeurs (sans le (x) que je supprime avant d'appliquer l'expression dans QGIS) : https://regex101.com/r/kqyWrZ/1

Dernière modification par p.jeremie (Sun 10 September 2023 23:13)

Hors ligne

 

#3 Mon 11 September 2023 14:58

Pascal1968
Participant occasionnel
Date d'inscription: 21 Aug 2023
Messages: 10

Re: QGIS: Extraction partielle chaine de caracteres

Salut Jérémie !

Grand merci pour cette réponse aussi rapide que complète !
Normalement, au niveau nomenclature des arbres, un cas comme Salix (x) sepulcralis _'Chrysocoma' s'écrit Salix x sepulcralis 'Chrysocoma'.
Seulement, au niveau des expressions que j'avais montées, il me fallait pouvoir distinguer ce qui est le nom du genre, le nom de l'espèce et le nom de la variété. Sans compter toutes les variantes qui ne comprenne pas de nom d'espèces ou qui possède un 'x' de liaison car ce sont des cultivars.
Bref, le "(x)" et le " _" me permettait sans trop d'effort au résultat.
Pour rire, le fait des parenthèses autour du "x" me permettait d'éviter que ma fonction ne s'arrête sur le "x" de "saliX" au lieu de s'arrêter sur le "x" de liaison :-) Ca m'a rendu ce truc-là.
Le redoublement de l'espacement n'était pas non plus une erreur. Il me permettait de ne pas avoir le nom du cultivar qui venait s'afficher avec celui de l'espèce. Mais, bon, je l'admets, c'est du bricolage.

De mon très rapide petit test au boulot, tes trois expressions fonctionnent presque à la perfection. Je constate simplement que je me suis mal exprimé sur quelques détails.

Pour le "(x)", tu as raison. Je souhaite effectivement pouvoir récupérer le "x" (sans les parenthèses) dans le champs "Species".
Pour le Salix (x) sepulcralis _'Chrysocoma', le résultat escompté est donc:
Genus : Salix
Species: x sepulcralis
Cultivar: 'Chrysocoma'

De même les guillemets simples (') qui entourent le nom du cultivar doivent aussi être conservés. Ce qui n'est pas le cas ici.

Penses-tu qu'il soit possible de modifier tes trois expressions pour les utiliser directement sur les noms réels sans mes "(x)" et " _" qui me servent à séparer genre/espèce/variété ?

Je vais m'attaquer ce soir au site que tu m'as conseillé et qui me semble effectivement très intéressant. On est jamais trop vieux pour apprendre.

Merci d'avance pour la suite !

Hors ligne

 

#4 Mon 11 September 2023 15:08

p.jeremie
Participant assidu
Lieu: Valence
Date d'inscription: 10 Sep 2017
Messages: 427

Re: QGIS: Extraction partielle chaine de caracteres

Pascal1968 a écrit:

De mon très rapide petit test au boulot, tes trois expressions fonctionnent presque à la perfection. Je constate simplement que je me suis mal exprimé sur quelques détails.

Pour le "(x)", tu as raison. Je souhaite effectivement pouvoir récupérer le "x" (sans les parenthèses) dans le champs "Species".
Pour le Salix (x) sepulcralis _'Chrysocoma', le résultat escompté est donc:
Genus : Salix
Species: x sepulcralis
Cultivar: 'Chrysocoma'

De même les guillemets simples (') qui entourent le nom du cultivar doivent aussi être conservés. Ce qui n'est pas le cas ici.

Penses-tu qu'il soit possible de modifier tes trois expressions pour les utiliser directement sur les noms réels sans mes "(x)" et " _" qui me servent à séparer genre/espèce/variété ?


Est-ce que tu peux fournir des exemples des noms réels afin de pouvoir se baser dessus ?

Hors ligne

 

#5 Mon 11 September 2023 15:18

Pascal1968
Participant occasionnel
Date d'inscription: 21 Aug 2023
Messages: 10

Re: QGIS: Extraction partielle chaine de caracteres

Re salut,

J'ai trouvé pour les guillemets simplets à réafficher. J'ai changé '[_'']' en '[_]' à la fin de l'expression.

Par contre, réafficher le "x" sans les parenthèses reste un problème pour moi.
En remplaçant  (  replace(fullname,'(x) ','') par (  replace(fullname,'(x) ','x'), j'obtiens Species : xsepulcralis
Et si je remplace par (  replace(fullname,'(x) ','x '), j'obtiens Species: NULL

Je continue à chercher de mon côté.

Hors ligne

 

#6 Mon 11 September 2023 15:30

Pascal1968
Participant occasionnel
Date d'inscription: 21 Aug 2023
Messages: 10

Re: QGIS: Extraction partielle chaine de caracteres

Voici tous les cas "types" que j'ai pu rencontrer jusqu'à présent:

Abies alba => Genus : Abies et Species : alba
Acer campestre 'Elsrijk' => Genus : Acer Species : campestre et Cultivar : 'Elsrijk'
Acer platanoides 'Autumn Blaze' => Genus : Acer Species : platanoides et Cultivar : 'Autumn Blaze' (c'est une variation du cas précédent avec deux mots pour la variété (cultivar)
Aesculus x carnea => Genus : Aesculus et Species : x carnea
Salix x sepulcralis 'Chrysocoma'=> Genus : Salix Species : x sepulcralis et Cultivar : 'Chrysocoma'
Betula utilis var. jacquemontii => Genus : Betula Species : utilis et Cultivar : var. jacquemontii
Crataegus crus-galli => Genus : Crataegus et Species : crus-galli
Crataegus laevigata 'Paul's Scarlet' => Genus : Crataegus Species : laevigata et Cultivar : 'Paul's Scarlet'
Ilex 'Nellie R. Stevens' => Genus : Ilex Pas de Species et Cultivar : 'Nellie R. Stevens'

Je pense que tout y est :-)
Je ne peux pas dire que les botanistes nous ont faciliter la tâche pour faire des bases de données...

Merci d'avance !

Hors ligne

 

#7 Tue 12 September 2023 14:04

Pascal1968
Participant occasionnel
Date d'inscription: 21 Aug 2023
Messages: 10

Re: QGIS: Extraction partielle chaine de caracteres

Bonjour Jeremie,

Merci pour le site Regex101. Très intéressant. J'ai aussi fait le tour de deux trois sites explicatifs à ce sujet.
En partant de ton exemple, j'en suis arrivé ici pour le moment: https://regex101.com/r/tcwFZO/7

Pas parfait même si cela prend forme. je ne peux pas dire que je sois très doué de ce côté-là...

En annexe la capture d'écran avec mes commentaires. cela peut aider.

Merci d'avance !


Fichier(s) joint(s) :
Pour accéder aux fichiers vous devez vous inscrire.

Hors ligne

 

#8 Tue 12 September 2023 21:55

p.jeremie
Participant assidu
Lieu: Valence
Date d'inscription: 10 Sep 2017
Messages: 427

Re: QGIS: Extraction partielle chaine de caracteres

Bonjour,

J'ai fait une version 8 puis finalement 9 de ta regex.
https://regex101.com/r/tcwFZO/9

Elle répond a priori à tous les cas que tu as mentionnés.

Code:

^([a-zA-Z]+) (x? ?[a-zA-Z-]*) ?(.*)$

3 groupes :
- une suite d'au moins 1 lettre (le '+')
(une espace)
- un groupe pouvant être vide car composé de : caractère x puis espace répétés chacun 0 ou 1 fois (le '?') puis des lettres ou un tiret répétés 0 à n fois (le '*')
(une espace optionnelle grâce au '?')
- un groupe composé de n'importe quel caractère (le '.') répété 0 à n fois (le '*')
et la fin de ligne (le '$')

Hors ligne

 

#9 Wed 13 September 2023 08:16

Pascal1968
Participant occasionnel
Date d'inscription: 21 Aug 2023
Messages: 10

Re: QGIS: Extraction partielle chaine de caracteres

Bonjour Jeremie,

C'est absolument parfait !
J'avais essayé de regrouper les deux parties composant le Species mais je m'y étais mal pris. J'avais fait deux sous-groupes dans le groupe de Species. Mais, apparemment je l'avais mal écrit. Manque de pratique smile

Encore merci pour ton aide et belle journée !

Pascal

Hors ligne

 

Pied de page des forums

Powered by FluxBB