Remplace tout les \n entre "" dans une chaine [php] - PHP - Programmation
Marsh Posté le 24-04-2007 à 16:01:42
il y a aurait quelqu'un qui métrise les regexp? car j'ai essayer sans succès....
Marsh Posté le 24-04-2007 à 16:20:02
le mieux c'est de trouver un exemple tout fait, parcequ'à moins d'être autiste...
Marsh Posté le 24-04-2007 à 17:36:05
Bah je vois pas du tout ce qu'il y a de dur là. Suffit de regarder n'importe quel tuto sur les regexp.
Marsh Posté le 24-04-2007 à 17:40:26
j'ai rien compris a ce que tu veux faire...
Marsh Posté le 24-04-2007 à 17:41:16
ReplyMarsh Posté le 24-04-2007 à 17:42:16
ounaÿd
keskidisais comme conenrie ?
Marsh Posté le 24-04-2007 à 17:43:41
Pablo Escrobarbe a écrit : Han MagicBuzz a supprimé discretos un message |
ben ouais, parceque je trouvais pas mon intervention très utile
Marsh Posté le 24-04-2007 à 17:45:10
Sinon, ça peut aussi être un extract de données, formattées, qui contiennent des \n et il doit les interpréter avec un langage qui prends un autre caractères d'échappement.
M'enfin dans tous les cas, je pense pas que ce soit bien important de savoir par quoi il veut remplacer (c'est pour ça que j'avais viré mon post )
Marsh Posté le 24-04-2007 à 17:47:24
bah je vois pas en quoi il faut être autiste pour faire sa regexp, c'est tout
Marsh Posté le 24-04-2007 à 17:48:40
pour faire "sa" regexp non, pour faire des regexp en général.
mais si tu sais écrire des regexp, tu peux pas comprendre
Marsh Posté le 24-04-2007 à 17:51:46
les regex, cay le bien
Marsh Posté le 26-04-2007 à 08:56:58
mon problème est le suivant, j'ai un fichier xls que j'enregistre en csv.
Le problème c'est lorsque que dans une cellule j'ai un texte sur plusieurs lignes, dans mon fichier csv c'est pareil il me fait des retour à la ligne et le traitement n'est pas possible correctement avec php.
il faudrait que chaque ligne reste sur une ligne et pas sur plusieurs
Marsh Posté le 26-04-2007 à 10:25:57
Ptain mais au lieu d'hurler que les regexs "cay le bien" y'en a pas un pour l'aider /FOU/ /FOU/ ???
Les regexs dans ce cas là c'est vraiment pas le plus simple. Je pense que tu aurais plus vite fait de faire un str_replace sur la sous-chaine entre les deux quotes
Si tu tiens vraiment a faire une regex, dans ton cas précis tu ferais mieux de prendre le problème à "l'envers".
C'est à dire remplacer tous les retours à la ligne qui ne marquent pas la fin d'une ligne dans ton fichier csv. Donc annuler tous les retours à la ligne qui ne suivent pas un ;.
Auquel cas la regex devient relativement simple, à condition de savoir se servir des assertions ( arrière négative dans ce cas précis):
Code :
|
ps pour MagicBuzz, petitpois2, zecrazytux> avant de dire que c'est facile ou qu'il suffit de lire un tuto, essayez donc de la faire ...
et pour finir une quote Masklinn staïlle:
Citation : Some people, when confronted with a problem, think I know, Ill use regular expressions. Now they have two problems. |
Marsh Posté le 26-04-2007 à 11:11:19
anapajari a écrit : Ptain mais au lieu d'hurler que les regexs "cay le bien" y'en a pas un pour l'aider /FOU/ /FOU/ ??? |
On n'y peux rien si on n'est pas autistes nous
anapajari a écrit : Les regexs dans ce cas là c'est vraiment pas le plus simple. Je pense que tu aurais plus vite fait de faire un str_replace sur la sous-chaine entre les deux quotes |
Absolument pas d'accord, un str_replace va t'obliger à faire une usine à gaz selon moi
anapajari a écrit : Si tu tiens vraiment a faire une regex, dans ton cas précis tu ferais mieux de prendre le problème à "l'envers". |
Faux, un CSV, déjà utilise "," et non ";" et aucune ligne ne se termine par ";" (ou "," ) s'il est écrit convenablement. En tout cas, Excel n'en met pas.
anapajari a écrit : Auquel cas la regex devient relativement simple, à condition de savoir se servir des assertions ( arrière négative dans ce cas précis):
|
Je pige rien à ta regexp. Mais c'est pas ça du tout à quoi je pensais. Bon, vais faire un tour dans une doc sur les regexp pour pondre ce que je testerais. Je compte sur toi pour l'aider à la débuguer ensuite
anapajari a écrit : ps pour MagicBuzz, petitpois2, zecrazytux> avant de dire que c'est facile ou qu'il suffit de lire un tuto, essayez donc de la faire ...
|
Ben quoi ? T'aime pas les challenges ?
Marsh Posté le 26-04-2007 à 11:18:52
Citation : |
Marsh Posté le 26-04-2007 à 11:24:37
Ouais bah on pouvait pas lui faire sa regex vu qu'il donnait pas ce qu'il voulait
Maintenant qu'il l'a dit je vois pas trop parce que je suis une merdasse
Marsh Posté le 26-04-2007 à 11:27:22
[^|,|"]"[^"]?*([\r\n])[^"]?*"[,|$,|"]
=> Tout ce dont je suis sûr, c'est que ça marche pas
Le but du jeu, c'est d'isoler une sous-chaîne entre doubles quotes lorsque les doubles quotes commencent immédiatement après un début de ligne ou une virgule, et terminent immédiagement avant une fin de ligne ou une virgule.
Et il ne faut pas que cette sous-chaîne contienne de doubles quotes...
Et enfin, il faut que cette sous-chaîne contienne un retour à la ligne, qu'on met entre () afin de l'isoler pur itiliser la fonction reg_replece()
Marsh Posté le 26-04-2007 à 11:31:48
Pablo Escrobarbe a écrit : Ouais bah on pouvait pas lui faire sa regex vu qu'il donnait pas ce qu'il voulait |
En tout cas, pour moi, quelqu'un qui sait écrire une regexp (donc pas moi ) c'est extrêment "simple" à faire.
Par contre, le faire à la main, ça nécessite une lecture caractère par caractère, en faisant gaffe à l'encoding, faire une pile pour compter les " et les , etc. etc. plus le respect d'un algo imbittable que je viens de décrire dans mon précédent poste.
C'est le genre d'usines à gaz typiques que les regexp sont là pour éviter.
Marsh Posté le 26-04-2007 à 11:33:00
le probleme du caractere spécial c'est par exemple la virgule, danc ce cas t'es ouned: comment tu repere une virgule non voulue, d'une virgule propre au format CSV ?
Marsh Posté le 26-04-2007 à 11:35:03
zecrazytux a écrit : le probleme du caractere spécial c'est par exemple la virgule, danc ce cas t'es ouned: comment tu repere une virgule non voulue, d'une virgule propre au format CSV ? |
Parceque entre mes " " " je prends n'importe quel caractère sauf " " ", donc si y'a des virgules, "logiquement" ma regexp foireuse ne la prends pas en compte. Après, vu qu'elle est mal écrite, elle la prends peut-être en compte, mais c'est pas censé être le cas
En tout cas, c'est bien pour ça que je dis que c'est la merde à gérer avec une lecture à la main du fichier : y'a plein de petits cas à la con qui sont chiants à coder (alors qu'en regexp, t'ajoutes 3 pauvres caractères à ta ligne d'autiste et ça marche !)
Marsh Posté le 26-04-2007 à 11:38:19
MagicBuzz a écrit : Le but du jeu, c'est d'isoler une sous-chaîne entre doubles quotes lorsque les doubles quotes commencent immédiatement après un début de ligne ou une virgule, et terminent immédiagement avant une fin de ligne ou une virgule. |
presque, sauf que : "bla bla \" bla bla" => quote à l'intérieur de quote
=> donc je dirais chercher les bouts entre des quotes non précédées d'anti slash (assertion arrière négative), puis un callback (option e) str_replace
aller les gars, ça vous fera bosser les regexp
Marsh Posté le 26-04-2007 à 11:39:42
soju a écrit : presque, sauf que : "bla bla \" bla bla" => quote à l'intérieur de quote |
nan, en CSV on utilise "" au lieu de \"
=> l'équilibre est tout bête à contrôler : une sous-chaine est délimitée par ^" ," "" et "$ ", "" (au choix une des trois séquances à chaque fois)
C'est logiquement ce que je teste dans ma regexp mais à mon avis c'est mal écrit
Marsh Posté le 26-04-2007 à 11:42:47
en fait, je viens de corriger et ça me semble déjà mieux là
Marsh Posté le 26-04-2007 à 11:44:19
MagicBuzz a écrit : nan, en CSV on utilise "" au lieu de \" |
je rectifie : nan, en CSV version excel on utilise "" au lieu de \"
Il n'y a aucune norme csv, et même si il en avait une, excel ne la respecterait sûrement pas...
sinon c'est presque pareil : quotes non précédées de quote
Marsh Posté le 26-04-2007 à 11:48:01
En fait, c'est ça, c'est mon dernier mot.
Une chaîne de caractères qui contient des séquences spéciales en CSV c'est :
Commence par le caractère " précédé soit d'un début de ligne, d'une virgule ou d'un caractère ".
Suivit d'une séquence de zéro ou plus caractères autres que ".
Terminé par le caractère " suivit soit d'une fin de ligne, d'une virgule ou d'un caractère ".
Cas spécifique de ,"", (chaine vide) : ça marche
Cas spécifique d'une virgule noyée dans une chaîne : ,"azaz,", : ça marche quelle que soit la position de la ,
Cas spécifique d'un sauf de ligne noyé dans une chaîne : ," zerer\nssd", : ça marche aussi
le seul point qui peut être gênant, c'est ça :
"ssdsd"","",""ssdsd"
=> là très franchement je sais pas si ma regexp s'en sort
Marsh Posté le 26-04-2007 à 11:49:22
zecrazytux a écrit :
|
Bourdel
C'est quoi cette manie de toujours vouloir tous échapper à la sauce ANSI en dépit des règles imposées par une règle choisie ?
Je sais pas d'où il a sorti cette doc, mais très certainement pas de la doc d'Excel...
(ceci dit, ça change pas grand chose aux tests effectivement, ça le rends juste 10 fois plus long à écrire : l'échappement ANSI est une merde sans nom à matcher par regexp) -tout comme regexp est une merde sans nom à utiliser avec un langage qui respecte ANSI, puisqu'ils ont les mêmes caractères d'échappement...-
Marsh Posté le 26-04-2007 à 11:53:28
MagicBuzz a écrit : [^|,|[""]]?[^"]?*"[^"]?*([\r\n])[^"]?*"[,|$,|[""]]? |
ça s'écrirait comme ça plus simplement
Code :
|
Mais ça marche que s'il n'y a qu'un seul saut de ligne entre quotes ( le problème que j'évoquais plus haut) car dans ce cas précis l'option g est "annulée" par la s.
Du coup en toute théorie faudrait faire des sous-groupes:
Code :
|
mais la c'est plus possible d'utiliser les $ pour faire le replace ... donc on oublie
D'ou mon idée de dire, on remplace tous les espaces sauf ceux qui marquent réellement une fin de ligne.
Pour le format csv, je pensais que ça se terminait pas un ";" ( ou "," pour les extremistes, la n'était pas le point important).
Mais le fait qu'il n'y en ai pas, c'est pas plus mal. On va faire une regex qui remplace tous les retours à la ligne suivi d'un texte contenant un ";":
Code :
|
Sans voir son fichier difficile de dire, mais ça devrait fonctionner pas trop mal
edit: j'ai encore utilisé un ";" , il faut le remplacer par ","
MagicBuzz a écrit : En tout cas, pour moi, quelqu'un qui sait écrire une regexp (donc pas moi ) c'est extrêment "simple" à faire. |
sir, no, sir.
Des regex j'en bouffe depuis que je fais du perl. Et je te garantis que celle-ci n'est pas simple ( en tout cas pour moi).
Pour toute te dire, si j'avais ça a faire je le ferais en deux fois:
- un capture de tous les textes entre quotes qui contiennent au moins un espace
- boucle pour remplacer tous ces espaces dans chaque item trouver
Marsh Posté le 26-04-2007 à 12:07:49
! <= ça veut dire quoi ?
moi j'ai utilisé ça pour avoir la liste des caractères, et je le trouve pas
http://en.wikipedia.org/wiki/Regular_expression
Sinon, je suis pas sûr que tes expression marchent bien.
Citation : On va faire une regex qui remplace tous les retours à la ligne suivi d'un texte contenant un ";" |
=> Ca, tout seul, ça peut pas marcher !
"titi","va","à
",la","piscine"
"toto","va","à","la","plage"
=> Bah ici, le premier sauf de ligne, ça marche...
Mais le seconde (après "piscine" ), le saut de ligne est effectivement suivit par des "," alors qu'on ne veut surtout pas l'échapper.
D'où mes tests plus évolués : [^|,|"]"[^"]?*([\r\n])[^"]?*"[,|$,|"]
=> il faut s'assurer que le saut de ligne trouvé est bien à l'intérieur d'une chaîne
Par contre, effectivement, il faut faire un replace récursif au cas où il y ait plusieurs retours à la ligne dans une même chaîne.
Marsh Posté le 26-04-2007 à 12:30:41
MagicBuzz a écrit : ! <= ça veut dire quoi ? |
C'est une assertion négative, la doc de perl est assez bien faite à ce sujet si tu veux jeter un oeil:
Citation : (?!pattern) |
MagicBuzz a écrit :
|
t'as pas tort patator ...
MagicBuzz a écrit : D'où mes tests plus évolués : [^|,|"]"[^"]?*([\r\n])[^"]?*"[,|$,|"] |
c'est tout caca ton truc
j'aurais tendance à le réécrire comme ça:
Code :
|
ça marcouille dans le cas simples ( ton exemple) mais s'il y a bcp de retour à la ligne ça merdouille:
Code :
|
donne
"titi","va","à",la","piscine avec |
MagicBuzz a écrit : Par contre, effectivement, il faut faire un replace récursif au cas où il y ait plusieurs retours à la ligne dans une même chaîne. |
Zouper , et après on parle d'usine à gaz avec str_replace !
Marsh Posté le 26-04-2007 à 12:58:35
ben si le moteur regexp est bien foutu, il ne fait l'appel que sur la sous-chaîne traîtée, et uniquement si il a déjà trouvé une occurence dans la sous-chaine, on peut pas dire que ce soit la mort (pour ça que je parle de "récursif" et non de "successif" )
Marsh Posté le 26-04-2007 à 13:00:46
sinon, je pige toujours pas ta regexp
"littéralement", elle fait quoi ?
sinon, la mienne corrigée du coup :
Code :
|
Marsh Posté le 26-04-2007 à 13:54:14
MagicBuzz a écrit : ben si le moteur regexp est bien foutu, il ne fait l'appel que sur la sous-chaîne traîtée, et uniquement si il a déjà trouvé une occurence dans la sous-chaine, on peut pas dire que ce soit la mort (pour ça que je parle de "récursif" et non de "successif" ) |
Nan mais ça marche pas comme ça hein
Reprenons ton exemple modifé:
# |
Sur la chaine "piscine ... amis"
le moteur va matcher "(piscine \n avec) puis ( ces \n amis) mais pas (avec \n ces) car les deux morceaux qui composent ce truc ont déjà été matchés.
MagicBuzz a écrit : sinon, je pige toujours pas ta regexp |
laquelle? celle la:
/[\r\n](?!.*?;)/ |
un retour à la ligne non suivi de "un texte suivi d'un point virgule"
celle la:
/[\r\n](([^,]*?)([\r\n])|",)/$1/gs |
un retour à la ligne suivi d'un texte suivi d'un retour à la ligne ou de l'expression ",
on remplace tout ça par le contenu de la 1ere parenthèse capturence $1
MagicBuzz a écrit :
|
t'as toujours le problème quand il y a plusieurs retours à la ligne.
edit: et elle marche pas du tout
Code :
|
donne (une fois corrigé l'inversion des * ? )
"titi","va" |
Marsh Posté le 26-04-2007 à 14:28:01
bon apparement pas tout le monde à compris mon problème je vais mettre un cas pratique :
6067;19.04.2007;20.04.2007;Workshop;Workshop;Lieu;Tous;320;;;;;NM;VD
7026;20.04.2007;20.04.2007;Colf Coaching ;"Golf Coaching Discover
14h00-18h00";Lieu;AP;190;;;;;AB;VD
la première ligne est correcte (pas de retour à la ligne)
la deuxième est sur deux lignes mais la valeur sur 2 lignes est entourées de "
voila j'éspère que c'est plus clair...
(les regexp j'ai beau essayé, j'arrive pas...
il faut remplacer tout les \n qui se trouve entre deux "
merci
Marsh Posté le 26-04-2007 à 14:30:46
Ca ça marche chez moi :
Code :
|
En fait, ça pmarche, sauf que marche qu'avec la première occurence
Même si je le lance de façon successive ensuite, il ne prends pas en compte la suite
Marsh Posté le 26-04-2007 à 14:34:43
simoes a écrit : 6067;19.04.2007;20.04.2007;Workshop;Workshop;Lieu;Tous;320;;;;;NM;VD |
Toutes les lignes "normales" se finissent pas VD? Ou par une liste de valeurs finie?
MagicBuzz a écrit : Ca ça marche chez moi : (en cours de correction en fait, ça marche pas
|
A vue de nez je dirais que le moteur de regex sur ton truc ça doit être POSIX et pas PCRE, du coup si (ça marche et) il eut s'en servir en php il faut utiliser ereg_* et pas preg_*
Marsh Posté le 24-04-2007 à 15:56:17
Hello,
voila je sèche sur un problème, je désire remplacer tous les \n entre des " " mais je trouve pas de solutions
j'ai bien essayer avec un str_replace, le problème c'est qu'il me les remplace tous mais ceux qui ne sont pas entre " ".
Merci de votre aide...