supprimer CRLF entre " dans fichier

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
Avatar du membre
Motard84
Niveau 1
Niveau 1
Messages : 11
Enregistré le : mar. 03 sept. 2024 19:21
Localisation : vaucluse
Status : Hors ligne

supprimer CRLF entre " dans fichier

#1

Message par Motard84 »

Bonjour,

je galère depuis plusieurs jours pour supprimer les retours de lignes situés entre guillemets.

Voici un exemple de texte à modifier:

Code : Tout sélectionner

X;Y;name;inscription;description;com_insee;com_nom
55.422553;-21.1161603002948;;;;97423;Les Trois-Bassins
4.1000169;50.1612663994162;Chapelle Delattre;;;59572;Solre-le-Château
-140.9066517;-18.1018004004722;Stèle RSMA;"RSMA-PF

Le 20 janvier 2022
M.Dominique SORAIN,
Haut Commissaire de la République en Polynésie française
a visité le chantier pédagogique du RSMA-PF à HAO,
en présence
de Mme Yseult BUTCHER-FERRY, mairesse de HAO,
du CA Jean-Mathieu REY, commandant supéri";;98720;Hao
1.10286062111345;49.4458920927511;;;;76540;Rouen
-3.9528841;47.7211379000032;Phare et fort de Penfret;;;29058;Fouesnant
1.8439592;43.7321450005395;;;;81011;Ambres
4.4901719;45.5162827004108;Croix Rouge;"1949
La Grand Grange de Saint-Chamond
1984";;42207;Saint-Chamond
2.1761641;42.8753788005331;;Jean de Lattre de Tassigny, Maréchal de France, 1911 - 1952;;11304;Quillan
-3.049979;47.60453460003;;;;56034;Carnac
2.2695351;44.5061126005078;;;;12013;Aubin
2.6433611;45.0580427004626;N-D des Méringes;;;15113;Mandailles-Saint-Julien
0.0655922;43.1389874005394;Monument aux morts;;;65479;Visker
-3.0809176;47.5927392000327;;;;56034;Carnac
0.3289716;45.5744587004033;Roc de Sers;Aménagements scénographiques sur le site, cabane de fouilles de Léon Henri Martin;;16368;Sers
1.7906642;43.2602578005411;;;;11231;Mézerville
3.214028;44.3278524005184;;;;48094;Massegros Causses Gorges
1.1106083;49.4416264995839;Nathan Ettinger;"Ici habitait Nathan Ettinger
Ne 1890
Arrete 6.5.1942
Deporte 22.6.1942
Auschwitz
Assassine";;76540;Rouen
5.6337607;46.7383604002134;;;;39388;Nevy-sur-Seille
3.0146205;44.3214514005187;;;;12270;Sévérac d'Aveyron
3.72956483620956;48.0006347548315;Église Saint-Florentin;;;89345;Saint-Florentin
2.7301507;45.514635000411;;;;63098;Chastreix
-0.7519277;49.240266699633;;;;14679;Subles
3.0460009;42.5617627005206;Le monolithe Exilio Español 1939;;"Monument marquant le lieux du camp d'Argeles sur Mer, ou sont passé les Républicains Espagnols qui fuyaient la guerre civile et le régime de Franco.
""Homme libre, souviens toi""

Pour comprendre et connaitre l'histoire, il faut visiter le mémorial qui se t";66008;Argelès-sur-Mer
3.7508453;45.3835729004271;;;;63139;Dore-l'Église
2.9946676;45.5793702004026;;;;63380;Saint-Nectaire
Voici ce que je cherche à faire:

Code : Tout sélectionner

3.0460009;42.5617627005206;Le monolithe Exilio Español 1939;;"Monument marquant le lieux du camp d'Argeles sur Mer, ou sont passé les Républicains Espagnols qui fuyaient la guerre civile et le régime de Franco.""Homme libre, souviens toi"" Pour comprendre et connaitre l'histoire, il faut visiter le mémorial qui se t";66008;Argelès-sur-Mer
J'ai essayer plusieurs Pattern (ex. : "([^"]*)\R([^"]*)" ), à chaque fois il me reste des Retour à la ligne.

Pour info, le fichier CSV contient environ 200 000 lignes donc je cherche avec StringRegEx car plus rapide que de décomposer chaque ligne, chercher les " supprimer les retours à la ligne.

Merci par avance.
Avatar du membre
TommyDDR
Modérateur
Modérateur
Messages : 2102
Enregistré le : mar. 22 juil. 2008 21:55
Localisation : Nantes
Status : Hors ligne

Re: supprimer CRLF entre " dans fichier

#2

Message par TommyDDR »

Si tu ne veux pas te prendre la tête :
StringReplace($txt, @CRLF, "")
Si ça ne fonctionne pas, remplace @CRLF par @LF et si tu veux un espace, remplace "" par " "
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
Avatar du membre
Motard84
Niveau 1
Niveau 1
Messages : 11
Enregistré le : mar. 03 sept. 2024 19:21
Localisation : vaucluse
Status : Hors ligne

Re: supprimer CRLF entre " dans fichier

#3

Message par Motard84 »

TommyDDR a écrit : jeu. 23 janv. 2025 20:33 Si tu ne veux pas te prendre la tête :
StringReplace($txt, @CRLF, "")
Si ça ne fonctionne pas, remplace @CRLF par @LF et si tu veux un espace, remplace "" par " "
Bonsoir,

Merci mais cela va remplacer tous les @CRLF, je souhaites uniquement supprimer ceux entre guillemets....
Avatar du membre
TommyDDR
Modérateur
Modérateur
Messages : 2102
Enregistré le : mar. 22 juil. 2008 21:55
Localisation : Nantes
Status : Hors ligne

Re: supprimer CRLF entre " dans fichier

#4

Message par TommyDDR »

Oui, désolé, je devais être fatigué quand j'ai répondu :lol:

Si tu mets tes données dans un csv (je suppose qu'elles viennent d'un fichier), il y a surement plus propre mais tu peux faire ça :
#include <Array.au3>
#include <Excel.au3>

Local $source = @ScriptDir & "\datas.csv"
Local $nbCols = 7

Local $array = readCsv($source, $nbCols)

_ArrayDisplay($array)

Func readCsv($fileName, $nbCols, $startRow = 0)
   Local $ret[0][$nbCols]
   Local $row = $startRow
   Local $oExcel = _Excel_Open(False, False, False, False)
   Local $oWorkbookSrc = _Excel_BookOpen($oExcel, $source)
   Local $colLetter = _Excel_ColumnToLetter($nbCols)
   Local $cells
   While 1
      $row += 1
      $cells = _Excel_RangeRead($oWorkbookSrc, Default, "A" & $row & ":" & $colLetter & $row)
      If(StringLen($cells[0][0]) > 0) Then
         _ArrayAdd($ret, $cells)
      Else
         ExitLoop
      EndIf
   WEnd
   _Excel_BookClose($oWorkbookSrc)
   _Excel_Close($oExcel)
   Return $ret
EndFunc
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
Avatar du membre
sylvanie
Niveau 11
Niveau 11
Messages : 1556
Enregistré le : jeu. 26 juil. 2007 21:31
Localisation : Paris
Status : Hors ligne

Re: supprimer CRLF entre " dans fichier

#5

Message par sylvanie »

Coucou, désolé j'arrive un peu tard.
J'étais parti sur un remplacement général des @CRLF par un ";" et faire une machne à état qui reconstitue les lignes en fonction du nombre de ";" comptés et si on est situé entre 2 '"' . Un peu lourd ... mais cette version peut fonctionner sur un PC sans Excel.
$INPUT_FILE=@ScriptDir&"\input_csv.txt"
$OUTPUT_FILE=@ScriptDir&"\output_csv.txt"
$hnd_out=FileOpen($OUTPUT_FILE,2)
if ($hnd_out=-1) Then Exit 1

$CONTENT=FileRead($INPUT_FILE)
$CONTENT=StringRegExpReplace($CONTENT,@CRLF,";")
$CURRENT_LINE=""
$MAX_COUNT=7
$CPT_SEMICIOLON=0
$CPT_DOUBLEQUOTE=0
For $INDICE =0 to StringLen($CONTENT)
   $CHAR=StringMid($CONTENT,$INDICE,1)
   Select
      Case $CHAR=';'
         If $CPT_DOUBLEQUOTE=0 Then
            $CPT_SEMICIOLON+=1
            If $CPT_SEMICIOLON=$MAX_COUNT Then
               $RET=FileWriteLine($hnd_out,$CURRENT_LINE)
               $CURRENT_LINE=""
               $CPT_SEMICIOLON=0
               ContinueLoop
            EndIf
         Else
            $CURRENT_LINE&=" "
            ContinueLoop
         EndIf
         $CURRENT_LINE&=$CHAR
      Case $CHAR='"'
         $CPT_DOUBLEQUOTE=Mod($CPT_DOUBLEQUOTE+1,2)
      Case Else
         $CURRENT_LINE&=$CHAR
   EndSelect
Next
FileWriteLine($hnd_out,$CURRENT_LINE)
FileClose($hnd_out)
$CONTENT=FileRead($OUTPUT_FILE)
ConsoleWrite($CONTENT&@CRLF)
 
Toi qui cherche à mettre le doigt sur la solution, appuie sur F1.
Avatar du membre
jguinch
Modérateur
Modérateur
Messages : 2514
Enregistré le : lun. 14 févr. 2011 22:12
Status : Hors ligne

Re: supprimer CRLF entre " dans fichier

#6

Message par jguinch »

Autre possibilité :

Code : Tout sélectionner

$content = FileRead("c:\tmp\test.txt")

$withQuotes = StringRegExp($content, '(?s)"(?!").+?"(?!")', 3)

For $i = 0 To UBound($withQuotes) - 1
	$content = StringReplace($content, $withQuotes[$i],  StringRegExpReplace($withQuotes[$i], "\R", "") )
Next
Le script, ça fait gagner beaucoup de temps... à condition d'en avoir beaucoup devant soi !
Avatar du membre
TommyDDR
Modérateur
Modérateur
Messages : 2102
Enregistré le : mar. 22 juil. 2008 21:55
Localisation : Nantes
Status : Hors ligne

Re: supprimer CRLF entre " dans fichier

#7

Message par TommyDDR »

Je crois que ça va être la solution la plus simple ^^
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
Avatar du membre
Motard84
Niveau 1
Niveau 1
Messages : 11
Enregistré le : mar. 03 sept. 2024 19:21
Localisation : vaucluse
Status : Hors ligne

Re: supprimer CRLF entre " dans fichier

#8

Message par Motard84 »

jguinch a écrit : ven. 24 janv. 2025 16:32 Autre possibilité :

Code : Tout sélectionner

$content = FileRead("c:\tmp\test.txt")

$withQuotes = StringRegExp($content, '(?s)"(?!").+?"(?!")', 3)

For $i = 0 To UBound($withQuotes) - 1
	$content = StringReplace($content, $withQuotes[$i],  StringRegExpReplace($withQuotes[$i], "\R", "") )
Next
Bonjour,
merci cela fonctionne parfaitement (en tous cas sur l'extrait du fichier).
Je teste sur le fichier complet (290 000 lignes environ) et fais un retour.

NB: j'ai remplacer la ligne

Code : Tout sélectionner

$content = StringReplace($content, $withQuotes[$i],  StringRegExpReplace($withQuotes[$i], "\R", "") )
par

Code : Tout sélectionner

$content = StringRegExpReplace($content, $withQuotes[$i],  StringRegExpReplace($withQuotes[$i], "\R", "") )
afin d’accélérer le traitement (grosse différence)
Avatar du membre
Motard84
Niveau 1
Niveau 1
Messages : 11
Enregistré le : mar. 03 sept. 2024 19:21
Localisation : vaucluse
Status : Hors ligne

Re: supprimer CRLF entre " dans fichier

#9

Message par Motard84 »

Bonjour,

Code complet:

Code : Tout sélectionner

; Open the file for reading and store the handle to a variable.
Local $hFileOpen = FileOpen(@ScriptDir &  "\historic.csv", $FO_READ)

Global $content = FileRead($hFileOpen)

; Close the handle returned by FileOpen.
FileClose($hFileOpen)
$withQuotes = StringRegExp($content, '(?s)"(?!").+?"(?!")', 3)


;~ _ArrayDisplay($withQuotes)

Local $iNB = UBound($withQuotes) - 1 , $iPourcent

For $i = 0 To UBound($withQuotes) - 1

	if StringRegExp($withQuotes[$i], "\R",$STR_REGEXPMATCH) then
	;~ 	$content = StringReplace($content, $withQuotes[$i],  StringRegExpReplace($withQuotes[$i], "\R", "") )
		$content = StringRegExpReplace($content, "'" & $withQuotes[$i] & "'" ,  StringRegExpReplace($withQuotes[$i], "\R", ". ") )
		ConsoleWrite("+ =========================================================> OK" & @crlf)
	EndIf

$iPourcent = round(($i / $iNB) * 100,2) & "%"
	ConsoleWrite("< = " &  $i & "/" &  $iNB &  " " & $iPourcent & @crlf)
Next

Le code précédent avec mon fichier complet me génère l'erreur suivante (cela se produit lorsque $i > 34760):

Image

Je n'arrive pas à comprendre ce qui est en cause.

Voici le fichier (lien valable 30j) : fichier CSV


Merci.
Avatar du membre
jguinch
Modérateur
Modérateur
Messages : 2514
Enregistré le : lun. 14 févr. 2011 22:12
Status : Hors ligne

Re: supprimer CRLF entre " dans fichier

#10

Message par jguinch »

Oups, je viens de voir que mon expression régulière n'était pas top. J'ai fais un poil autrement, dis moi si ça te va
$content = FileRead("historic.csv")

$withQuotes = StringRegExp($content, '(?s);\K".+?"(?=;)', 3)

For $i = 0 To UBound($withQuotes) - 1
   If StringInStr($withQuotes[$i], @LF) Then  $content = StringRegExpReplace($content, "\Q" & $withQuotes[$i] & "\E",  StringRegExpReplace($withQuotes[$i], "\R", ""), 1 )
Next
Le script, ça fait gagner beaucoup de temps... à condition d'en avoir beaucoup devant soi !
rgx
Niveau 4
Niveau 4
Messages : 62
Enregistré le : sam. 16 nov. 2019 17:53
Status : Hors ligne

Re: supprimer CRLF entre " dans fichier

#11

Message par rgx »

Bonjour,

@Motard84 : la saturation de mémoire est possible à cause du chargement complet du fichier et de l'utilisation de certaines fonctions.
À part avec des langages spécialisés (comme perl) les expressions régulières sont souvent plus lentes que les fonctions internes de chaines.
Dans le cas de grands fichiers, il est préférable de traiter ligne par ligne.

Voici une petite bafouille sans expression régulière.
Avantage: fichier de test (258 612 lignes) traité en 7 secondes (sur mon i7 avec SSD)
Inconvénient: Elle ne traite pas les lignes qui ne comportent pas de guillemets (ce qui est le cas pour quelques lignes dans le fichier de texte, ex: L717 et suivantes). Mais ça doit pouvoir être fait avec quelques ligne de plus.

Principe:
  • Compter le nombre de guillemet dans chaque ligne.
  • S'il est pair, réécrire la ligne dans le fichier de sortie avec FileWrite (donc sans CR/LF)
  • S'il est impaire, réécrire la ligne dans le fichier de sortie avec FileWriteLine (donc avec CR/LF)

Code : Tout sélectionner

Local $hFileInput  = FileOpen(@ScriptDir &  "\historic.csv")
Local $hFileOutput = FileOpen(@ScriptDir &  "\historic_New.csv", 2)

$i = 0
$NbLines = 0
While 1
	$TmpLine = FileReadLine($hFileInput)
	If @error = -1 Then ExitLoop
	; Compter le nombre de guillemets
	$j = UBound(StringSplit($TmpLine, chr(34)))-2
	; S'il est impaire on affiche
	If $j / 2.0 <> Int($j / 2) Then
		;ConsoleWrite(StringFormat("% 8s", $i) & " - " & $j & " | " & $TmpLine & @CRLF)
		; SI nb " impaire: ecrire la ligne SANS CRLF
		FileWrite($hFileOutput, $TmpLine)
		$NbLines += 1
	Else
		; Si nb " paire écrire la ligne normale
		FileWriteLine($hFileOutput, $TmpLine)
	EndIf
	$i += 1
WEnd

FileClose($hFileInput)
FileClose($hFileOutput)

ConsoleWrite($NbLines & " Ligne(s) Modifiées.")
Ça ne fonctionne pas encore tout à fait car des blocs de texte posent problème sur le dernier guillemet (voir par exemple lignes 617 à 621 sur le fichier de sortie)

[Edit 2 après autre café]
Cette version donne un meilleur résultat ̶,̶ ̶m̶a̶i̶s̶ ̶f̶u̶s̶i̶o̶n̶n̶e̶ ̶l̶a̶ ̶l̶i̶g̶n̶e̶ ̶s̶u̶i̶v̶a̶n̶t̶e̶.̶ ̶(̶e̶x̶:̶ ̶l̶i̶g̶n̶e̶ ̶6̶0̶7̶)̶ Corrigé.
(@CRLF en début de ligne)

Code : Tout sélectionner

Local $hFileInput  = FileOpen(@ScriptDir &  "\historic.csv")
Local $hFileOutput = FileOpen(@ScriptDir &  "\historic_New.csv", 2)

$i = 0
$NbLines = 0
While 1
	$TmpLine = FileReadLine($hFileInput)
	If @error = -1 Then ExitLoop
	; Compter le nombre de guillemets
	$j = UBound(StringSplit($TmpLine, chr(34)))-2
	; S'il est impaire on affiche
	If ($j / 2.0 <> Int($j / 2)) Or ($j = 0) Then
		;ConsoleWrite(StringFormat("% 8s", $i) & " - " & $j & " | " & $TmpLine & @CRLF)
		; SI nb " impaire: ecrire la ligne SANS CRLF
		FileWrite($hFileOutput, " " & $TmpLine)
		ConsoleWrite(StringFormat("% 8s", $i) & " - " & $j & " | " & $TmpLine & @CRLF)
		$NbLines += 1
	Else
		; Si nb " paire écrire la ligne normale
		FileWrite($hFileOutput, @CRLF & $TmpLine)
	EndIf
	$i += 1
WEnd

FileClose($hFileInput)
FileClose($hFileOutput)

ConsoleWrite($NbLines & " Ligne(s) Modifiées.")
Hum, encore 25 lignes non modifiées (à cause de "" parfois))
Fichier output ouvert avec éditeur de texte et testé avec:

Code : Tout sélectionner

^(?:(?!-?\d+\.\d+;).)*$
Avatar du membre
Motard84
Niveau 1
Niveau 1
Messages : 11
Enregistré le : mar. 03 sept. 2024 19:21
Localisation : vaucluse
Status : Hors ligne

Re: supprimer CRLF entre " dans fichier

#12

Message par Motard84 »

Bonsoir @rgx,

merci pour les explications et le code.

Je regarde cela à mon retour.
Avatar du membre
Motard84
Niveau 1
Niveau 1
Messages : 11
Enregistré le : mar. 03 sept. 2024 19:21
Localisation : vaucluse
Status : Hors ligne

Re: supprimer CRLF entre " dans fichier (Résolu)

#13

Message par Motard84 »

Bonsoir,

Merci pour tous,

J'ai réussi grâce aux bouts de codes donnés.

Bonne soirée.
Répondre