[PHP][manipulation a l'intérieur d'un chaine]

Résolu/Fermé
efflamm Messages postés 22 Date d'inscription jeudi 18 janvier 2007 Statut Membre Dernière intervention 30 janvier 2008 - 18 janv. 2007 à 23:34
Ssylvainsab Messages postés 2884 Date d'inscription samedi 29 juillet 2006 Statut Modérateur Dernière intervention 15 août 2020 - 19 janv. 2007 à 16:55
Bonjour,
Je transfère des données d'un logiciel à un autre via un fichier texte que je fais parser par l'utilisateur via une adresse web locale d'un serveur linux debian (apache2,php4)

La moulinette qui "parse" le fichier lignepar ligne permet de "formater" les champs et d'enregistrer le nouveau fichier pour que l'autre logiciel veuille bien l'importer (le séparateur de champ est la virgule).

Une ligne type est représentée ainsi que suit :

champ1,champ2,champ3,champ4,champ5,etc,champ de la 7ième virgule,,,,champ11
et se termine par un retour à la ligne.

Je souhaite modifier une chaine après la 7ième virgule..Je n'y arrive vraiment pas.J'ai essayé à peu près tout ce que je sais faire en php.

Il me semble possible de le faire en alimentant une base SQL à partir de mon fichier texte, ainsi je pourrais balader mon "pointeur" dans le 7ième champ des lignes matchées et y faire ce que je veux. le volume d'information traitée etant faible( un fichier type comporte 200 lignes) je le ferais que si je n'ai pas d'autre choix.

Je pense qu'il est aussi possible de faire un appel system vers sed ou awk afin de traiter les lignes.je suis en train de regarder de ce coté là pour l'instant.

Il existe trés certainement d'autre solution dans d'autre langage, comme par exemple perl. Mais cela impliquerait de refaire complètement le script.Au cas ou quelqu'un aurais une solution dans un autre langage, c'est à ma portée de réécrire complètement le script.

Toute aide est la bienvenue, merci d'avance ;-)
A voir également:

7 réponses

efflamm Messages postés 22 Date d'inscription jeudi 18 janvier 2007 Statut Membre Dernière intervention 30 janvier 2008 3
19 janv. 2007 à 09:41
j'ajoute la portion du code concerné.



// verif fichier de donnée
if(file_exists('import.txt'))
	{
	// on efface le précedent export
	if(file_exists('export.txt'))
     		{
          	unlink('export.txt');
     		}

	$FicEntree = fopen("import.txt", "r");
	$FicSortie = fopen("export.txt", "w+");
	echo '<br>Generation des lignes d\'ecritures<br>';

	while (!feof($FicEntree))
		{       $buffer = fgets($FicEntree, 4096);

	        $search = '"';
        	$replace = '';
        	$result0 = str_replace($search, $replace, $buffer);

	        $search = ',,';
        	$replace = ',';
        	$result1 = str_replace($search, $replace, $result0);

	        $search = 'VT,0';
        	$replace = 'VT,411000,';
        	$result2 = str_replace($search, $replace, $result1);

		$search = '707100,';
        	$replace = '707100,,';
        	$result3 = str_replace($search, $replace, $result2);

        	$search = '445710,';
        	$replace = '445710, ,';
        	$result4 = str_replace($search, $replace, $result3);

        	$search = '708500,';
        	$replace = "708500,,";
        	$result5 = str_replace($search, $replace, $result4);

        	$search = ',C';
        	$replace = '';
        	$result6 = str_replace($search, $replace, $result5);


		$mystring = $result5;
		$findme   = ',C';
		$pos = strpos($mystring, $findme);
		if ($pos === false)
        		{
			// etat inintéressant, la chaine n'est pas présente.
			// ce n'est pas fatal.
			}
		else
        		{
        		// ici je souhaite altérer la ligne courante , mais je ne sais pas comment m'y prendre.
		// je dois insérer une virgule après la 7ième virgule en partant de la gauche.
		// C'est ici mon problème
		        }
		// saut de ligne html	
		$search = ',EUR';
		$replace = ',EUR<br>';
		$result7 = str_replace($search, $replace, $result6);

		// on écrit les données dans le fichier de sortie sans la modif html
		fputs($FicSortie,$result6, 4096);
		// on affiche les données pour le navigateur
		echo $result7;
		}
	}
else
	{
   	echo '<br><font color=red size=3><center>ERREUR FATALE : Le fichier import.txt n\'existe pas</center></font><br>';
   	exit;
	}
echo 'Generation terminée<br>';
echo 'Fermeture des fichiers<br>';


fclose($FicEntree);
fclose($FicSortie);

1
Reivax962 Messages postés 3671 Date d'inscription jeudi 16 juin 2005 Statut Membre Dernière intervention 11 février 2021 1 011
19 janv. 2007 à 11:04
Bonjour,

La solution à ton problème passe par les expressions rationnelles.
Pour transformer la 7e virgule en deux virgules, utilise la fonction suivante :

$result6point5 = ereg_replace("(([^,]*,){7})(.*)", "\\1,\\3", $result6);

Pour l'explication : la fonction ereg_replace(string pattern, string replace, string cible) fait une recherche sur une chaine, d'après le paramètre pattern. Elle remplace ce pattern (motif, en Anglais) par ce qu'on lui donne en deuxième argument.

Le pattern que j'utilise est "(([^,]*,){7})(.*)"
On remarque 3 groupes parenthésés :
([^,]*,), que l'on va appeler \\2 (par convention de php, 2 parce que c'est la 2e parenthèse ouvrante)
(\\2{7}), que l'on va appeler \\1
et enfin
(.*), que l'on appelle \\3

Explication de chaque bloc.

\\1 signifie "\\2 est répété 7 fois".

\\2 signifie "tout sauf une virgule, répété indéfiniment, suivi d'une virgule. On reconnaît donc bien un bloc du style "abcdef,"

Donc, pour en revenir à \\1 , on comprend qu'on en arrive à la 7ème virgule.

\\3, lui, est tout simple : il signifie bêtement "n'importe quel caractère répété indéfiniment". C'est la fin de ta chaîne, qui n'a pas d'importance.

Ensuite, le deuxième argument, la chaine de remplacement.
C'est tout bête : je prends tout ce qu'il y a avant (soit "\\1"), je rajoute une virgule (c'est ce que tu veux faire, non ?), puis je colle derrière tout le reste, \\3. Ca donne bien "\\1,\\3".

Je t'invite à rechercher plus d'infos sur les expressions rationnelles sur le web, il doit y en avoir plein. (cherches aussi "expressions régulières", c'est une mauvaise traduction de l'anglais "regular expression", mais c'est très répendu...)

J'espère ne pas t'avoir trop embrouillé ^^

Xavier
0
Reivax962 Messages postés 3671 Date d'inscription jeudi 16 juin 2005 Statut Membre Dernière intervention 11 février 2021 1 011
19 janv. 2007 à 11:07
Voilà, j'ai appliqué cette fonction à une chaine de test, et cela a donné :
$string_orig = "je, suis, une, chaine, avec, au, moins, sept, virgules, séparant, les, mots";
echo $string_orig;
$string_modif = ereg_replace("(([^,]*,){7})(.*)", "\\1,\\3", $string_orig);
echo "<br>".$string_modif;
Résultat :

je, suis, une, chaine, avec, au, moins, sept, virgules, séparant, les, mots
je, suis, une, chaine, avec, au, moins,, sept, virgules, séparant, les, mots
-1
efflamm Messages postés 22 Date d'inscription jeudi 18 janvier 2007 Statut Membre Dernière intervention 30 janvier 2008 3
19 janv. 2007 à 11:10
wa !.. merci.
C'est la ou se voit la différence entre un amateur et un pro.
mille merci, j'intègre ça dès que j'en aurais le temps ce matin !
1
efflamm Messages postés 22 Date d'inscription jeudi 18 janvier 2007 Statut Membre Dernière intervention 30 janvier 2008 3
19 janv. 2007 à 14:55
par contre ceci oui :

-------snip---------

$result5 = str_replace($search, $replace, $result4);
                $mystring = $result5;
                $findme   = ',C';
                $pos = strpos($mystring, $findme);
                if ($pos === false)
                        {$result6=$result5;}
                else
                        {
                        echo'<font color=red size=4>|</font>';
                        $result6 = ereg_replace("(([^,]*,){7})(.*)", "\\1,\\3", $mystring);
                        }
                $search = ',C';
                $replace = '';
                $result7 = str_replace($search, $replace, $result6);
                $search = ',EUR';
                $replace = ',EUR<br>';
                $resulthtml = str_replace($search, $replace, $result7);
                fputs($FicSortie,$result7, 4096);
                echo $resulthtml;
----snip----


le fameux etat pas intéressant dans ma boucle if plus haut , en fait il est interessant puisqu'il permet de dire à la boucle while (!feof()) ne touche pas à cette ligne. C'est ça qui m'échappais!
-----
J'ai des incohérences cependant , mais ça ne concerne plus ce problème précis.Voici :
Soit le morceau de ligne non parsée suivant
( ... ) VT,0YYYYYYY, ( ....)

D'après la moulinette ça devrait devenir

( .... ) VT,411000,YYYYY, ( ....)

Or voici ce qui arrive parfois seulement :

( ... ) VT,411000YYYYY, ( .....)

Cela arrive sur 3-4 lignes par fichier.Il y a surement une explication rationelle à ceci. Une particularité de la ligne, ou peut-etre que les fichiers sont hantés tout simplement.

En tout cas on peux considérerle problème principal comme résolu.Et pour être plus précis, c'est un transfert de comptabilité EBP gestion commerciale v9 vers SAGE v14.
Merci encore !

PS : le code complet, peut-etre servira t'il à quelqu'un ayant le meme problème.
<?php 
echo '<br>Initialisation du traitement ...<br>';
echo '<br>Les donnees seront sauvegardees dans : export.txt'; 
echo '<br>Ouverture des fichiers ...<br>';
echo '<br>Si une ligne ne parait pas conforme , verifiez toujours export.txt<br>';
// verif fichier de donnée
if(file_exists('import.txt')) 
	{ 
		if(file_exists('export.txt')) 
			{ 
          		unlink('export.txt'); 
     			} 
	$FicEntree = fopen("import.txt", "r");
	$FicSortie = fopen("export.txt", "w+");
	echo '<br>Generation des lignes d\'ecritures<br>';
	while (!feof($FicEntree)) 
		{	
		$buffer = fgets($FicEntree, 4096);
		$search = '"'; 
		$replace = ''; 
		$result0 = str_replace($search, $replace, $buffer);
		$search = ',,';
        	$replace = ',';
        	$result1 = str_replace($search, $replace, $result0);	
		$search = 'VT,0';
		$replace = 'VT,411000,'; 
		$result2 = str_replace($search, $replace, $result1); 
		$search = '707100,';
        	$replace = '707100,,';
        	$result3 = str_replace($search, $replace, $result2);
		$search = '445710,';
        	$replace = '445710, ,';
        	$result4 = str_replace($search, $replace, $result3);
		$search = '708500,';
        	$replace = "708500,,";
        	$result5 = str_replace($search, $replace, $result4);
		$mystring = $result5;
		$findme   = ',C';
		$pos = strpos($mystring, $findme);
		if ($pos === false) 
			{$result6=$result5;} 
		else 
			{
			$result6 = ereg_replace("(([^,]*,){7})(.*)", "\\1,\\3", $mystring);
			}
		$search = ',C';
		$replace = '';
		$result7 = str_replace($search, $replace, $result6);
		$search = ',EUR';
		$replace = ',EUR<br>';
		$resulthtml = str_replace($search, $replace, $result7);
		fputs($FicSortie,$result7, 4096);
		echo $resulthtml;
		}
	} 
else 
	{ 
   	echo '<br><font color=red size=3><center>ERREUR FATALE : Le fichier import.txt n\'existe pas</center></font><br>';	
   	exit;
	} 
echo 'Generation terminée<br>';
echo 'Fermeture des fichiers<br>';
fclose($FicEntree);
fclose($FicSortie);

?> 


Merci encore Xavier ;-)

1
efflamm Messages postés 22 Date d'inscription jeudi 18 janvier 2007 Statut Membre Dernière intervention 30 janvier 2008 3
19 janv. 2007 à 16:02
HMM :)
deux petites corrections.
ici
$findme   = ',C';
$pos = strpos($mystring, $findme);

Il convient de préciser que $findme = ',C,' ceci afin de ne pas matcher un autre champ que ,C,

et pour la même raison :
$search = ',C';
$replace = ' ';
$result7 = str_replace($search, $replace, $result6);

Il convient de préciser $search =',C,' et replace = ','

ceci élimine des petits problèmes.
1

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Ssylvainsab Messages postés 2884 Date d'inscription samedi 29 juillet 2006 Statut Modérateur Dernière intervention 15 août 2020 825
19 janv. 2007 à 16:55
Salut.

Je n'ai pas lu tous le sujet (seulement les premiers messages), mais est-ce qu'un explode ne serait pas plus approprié ?
$champsArray=explode(',',meschamps);

a plus
0
efflamm Messages postés 22 Date d'inscription jeudi 18 janvier 2007 Statut Membre Dernière intervention 30 janvier 2008 3
19 janv. 2007 à 12:51
Ca marche mais..enfin pas tout à fait. Je m'explique en isolant 3 lignes types.
au départ on a ça :
1,011206,VT,0YYYY,,"XXXXXXXXX "," F061050", 3272.26,D,011206,EUR
2,011206,VT,707100,," XXXXXXXXX "," F061050", 2736.00,C,180107,EUR
3,011206,VT,445710,," XXXXXXXXX "," F061050", 536.26,C,180107,EUR

la moulinette l'écrit dans export.txt de la manière suivante :

1,011206,VT,411000,YYYY, XXXXXXXXXX , F061050, 3272.26,D,011206,EUR
2,011206,VT,707100,, XXXXXXXXX , F061050, 2736.00,C,180107,EUR
3,011206,VT,445710, , XXXXXXXXX, F061050, 536.26,C,180107,EUR

Jusque là tout va bien. Je sais que la fonction marche pris isolément sur une ligne ( verifié avec un echo de sa valeur).Si je tente d'exploiter son resultat , comme ici dans un str_replace et dans le cadre d'un if, c'est la cata totale.
$mystring = $result5;
$findme   = ',C';
$pos = strpos($mystring, $findme);
if ($pos === false)
        {}
else
        {
        $result6 = ereg_replace("(([^,]*,){7})(.*)", "\\1,\\3", $mystring);
        }
//$search = ',C';
//$replace = '';
//$result7 = str_replace($search, $replace, $result6);

$search = ',EUR';
$replace = ',EUR<br>';
$resulthtml = str_replace($search, $replace, $result6);

// on écrit les données dans le fichier de sortie sans la modif html
        fputs($FicSortie,$result6, 4096);
// on affiche les données pour le navigateur 

        echo $resulthtml;
-1
efflamm Messages postés 22 Date d'inscription jeudi 18 janvier 2007 Statut Membre Dernière intervention 30 janvier 2008 3
19 janv. 2007 à 13:50
je continue à bosser dessus ^^ des choses doivent m'échapper.
----
j'ai avancé un peu. Je comprend mieux comment fonctionne ereg_replace. Nul besoin de l'utiliser dans un if {} else {}, seulement dans ce cas il modifie également les lignes que je ne souhaite pas. Cependant ça ne me sors pas des résultats certainement correct par rapport au code, mais pas du tout fidèle à ce que je veux. C'est donc un gros pas en avant.

S'il modifie aussi les lignes que je ne souhaite pas, je peux sans doute m'y adapter si je supprime ,D par exemple. Ca compenserait l'ajout d'un champ vide.je teste.
----
ce que je dis au dessus ne marche pas.
----
-1