J'ai la saisie de texte suivante.

Group 1,Good,LEADS,"Leads Description 1 
 Leads Description 2","Note 1
 Note 2",1,100,210,10,Amt,15% 
 Group 2,Good, SWITCHING, Switching, Description 1, "Switching Note 1 
 Switching Note 2",4,130,210,15,Amt,15%
 Group 1,Service,LICENCE,Licence Description 1,Licence Note 1,2,200,400,5,Pct,15%

La description et la note peuvent être sur la même ligne ou avoir une valeur sur plusieurs lignes. Ce sont au total 3 lignes. Lorsque la description et la note sont sur plusieurs lignes, le texte est en Double Quotes "" donc pour les lignes sans description sur plusieurs lignes ou pour les notes, une simple explosion fonctionne mais pour l'un ou l'autre sur plusieurs lignes. J'utilise l'instruction suivante pour l'analyser.

preg_split("/\n|\r\n?/", $text);

Cette instruction fonctionne pour les lignes, elle ne doit prendre en compte qu'une seule condition pour considérer le texte entre guillemets comme une seule ligne.

Edit: le texte ci-dessus est attribué à $ text

1
HardCode 16 sept. 2020 à 16:17

2 réponses

Meilleure réponse

Au lieu de les fractionner, essayez de les regrouper par expression régulière:

<?php
$s = 'Group 1,Good,LEADS,"Leads Description 1 
 Leads Description 2","Note 1
 Note 2",1,100,210,10,Amt,15% 
 Group 2,Good, SWITCHING, Switching, Description 1, "Switching Note 1 
 Switching Note 2",4,130,210,15,Amt,15%
 Group 1,Service,LICENCE,Licence Description 1,Licence Note 1,2,200,400,5,Pct,15%
';


  if (preg_match_all('/([^\r\n"]+|"[^"]*")+/', $s, $pregres)) {
    print_r($pregres[0]);
  }

Production:

Array
(
    [0] => Group 1,Good,LEADS,"Leads Description 1 
 Leads Description 2","Note 1
 Note 2",1,100,210,10,Amt,15% 
    [1] =>  Group 2,Good, SWITCHING, Switching, Description 1, "Switching Note 1 
 Switching Note 2",4,130,210,15,Amt,15%
    [2] =>  Group 1,Service,LICENCE,Licence Description 1,Licence Note 1,2,200,400,5,Pct,15%
)

Explication de l'expression régulière

([^\r\n"]+|"[^"]*")+

Entre parenthèses, il y a deux options (séparées par ou |):

[^\r\n"]+ - recherche une séquence de caractères qui n'est PAS un retour chariot, un saut de ligne ou des guillemets doubles. Cela recherchera une piqûre sans guillemets jusqu'à ce qu'elle atteigne un saut de ligne

"[^"]*" - recherche une séquence qui commence et se termine par des guillemets doubles et contient tous les caractères à l'intérieur sauf les guillemets. Cela consommera toute la chaîne entre guillemets, y compris tous les sauts de ligne à l'intérieur des guillemets.

Ils sont regroupés entre parenthèses et le groupe entier est autorisé à se répéter (par + suivi des parenthèses. Cela consommera toute la chaîne jusqu'à ce qu'il y ait une nouvelle ligne en dehors des guillemets.

Citations répétées (par exemple "this is a ""quoted"" string") également consommées.

1
AterLux 16 sept. 2020 à 14:20

Vous pourriez utiliser (*SKIP)(*FAIL) pour consommer et ignorer les sous-chaînes entre guillemets, puis diviser uniquement sur les nouvelles lignes qui ne sont pas consommées auparavant. Je vais poursuivre la séquence d'échappement de nouvelle ligne (\R) avec \s* pour couper efficacement les lignes à gauche.

Code: (Démo)

$text = <<<TEXT
Group 1,Good,LEADS,"Leads Description 1 
 Leads Description 2","Note 1
 Note 2",1,100,210,10,Amt,15% 
 Group 2,Good, SWITCHING, Switching, Description 1, "Switching Note 1 
 Switching Note 2",4,130,210,15,Amt,15%
 Group 1,Service,LICENCE,Licence Description 1,Licence Note 1,2,200,400,5,Pct,15%
TEXT;

var_export(preg_split('~"[^"]*"(*SKIP)(*FAIL)|\R\s*~', $text));

Production:

array (
  0 => 'Group 1,Good,LEADS,"Leads Description 1 
 Leads Description 2","Note 1
 Note 2",1,100,210,10,Amt,15% ',
  1 => 'Group 2,Good, SWITCHING, Switching, Description 1, "Switching Note 1 
 Switching Note 2",4,130,210,15,Amt,15%',
  2 => 'Group 1,Service,LICENCE,Licence Description 1,Licence Note 1,2,200,400,5,Pct,15%',
)

Certes, cette technique ne fonctionnera pas bien si votre texte contient des guillemets doublés, mais la réponse d'AterLux souffrira de la même manière.


Alternativement, si vous ne voulez pas vous fier aux sous-chaînes de guillemets doubles ET que vos nouvelles lignes commencent toujours par Group puis un espace puis un entier puis une virgule, alors vous pouvez choisir: (Démo)

var_export(preg_split('~\R\h*(?=Group \d+,)~', $text, 0, PREG_SPLIT_NO_EMPTY));
0
mickmackusa 16 sept. 2020 à 15:16