# [Applescript] Fonction correction de doublons



## Astronight (16 Mars 2011)

Bonjour, j'ai besoin d'un script qui quand je le lance, analyse un document texte (écrit avec textedit).
Et si il trouve des doublons les retire.

Je vous explique par un exemple.

J'ai donc dans un fichier texte 40 lignes qui chacune contiennent une date, et à coté un nom
Dans mon cas: 
Nom : 12/11/2010
Prenom : 13/11/2010
Pomme : 13/11/2010
Pomme : 14/11/2010 
Date : 15/11/2010

Il se peut que j'ecrive une date en doublon (comme dans cet exemple).
Je voudrais donc supprimer la seconde entrée, (ici Pomme: 13/11/2010)
Mais je n'ai aucune idée de comment faire..

Si quelqu'un pourrait éclairer ma lanterne, (ou me donner une piste de reflexion..)

Merci !


Ps: si ca peut aider, ca me suffit pour mes besoins actuels de traquer les répétitions sur deux ou 3 lignes suivies


----------



## Astronight (16 Mars 2011)

Edit : Bon  J'ai réussi à creer la partie repérage du doublon.

Je recherche désormais une manière de supprimer la ligne du doublon.

Voici mon code pour l'instant


```
tell application "Finder"
	-- Initialisation des variables Mais (répertoire user) et PathFichier (alias du fichier à lire)
	set Mais to (a reference to home)
	set PathFichier to file "Fichier.txt" of folder "Desktop" of Mais as alias
	-- Ouverture et lecture du fichier de travail "NomFichier.txt"
	open for access PathFichier
	set ContenuFic to read PathFichier
	close access PathFichier
	set ListeLigne to every paragraph of ContenuFic
	repeat with Ligne in ListeLigne
		set Lien1 to item 1 of ListeLigne
	end repeat
end tell

repeat with x from 1 to 50
	set someText to item x of ListeLigne
	set AppleScript's text item delimiters to {":"}
	set emailAddress to text item 1 of someText
	
	-----Selectionner la partie avec Pomme 

	set someText to item (x + 1) of ListeLigne
	set AppleScript's text item delimiters to {":"}
	set emailAddress1 to text item 2 of someText
	
	
	if (emailAddress1 = emailAddress) then
		display dialog "Boulet" & emailAddress1
	end if
	
end repeat
```



Voila donc maintenant, au lieu de display dialog "Boulet" & emailAddress1 je veux plutot supprimer la ligne du doublon. 
Any ideas?


----------



## ceslinstinct (17 Mars 2011)

Astronight a dit:


> Edit : Bon  J'ai réussi à creer la partie repérage du doublon.
> 
> Je recherche désormais une manière de supprimer la ligne du doublon.


Bonsoir

Tu pose une question, et tu te répond sans nous donner le temps de réfléchir.

Regarde mon code, espérons qu'il te donneras des idées.


```
(*set liste to "Nom : 12/11/2010
Prenom : 13/11/2010
Pomme :13/11/2010
Pomme : 14/11/2010 
Date : 15/11/2010
Poire : 16/12/10
Orange : 1/12/10
Cerise : 16/12/2010
Abricot : 17/12/2010
Raisin :    18/12/2010"*)

property mem : {} as list -- Mémoire des dates lues
property newList : "" -- Nouveau listing
property liste : "" -- Contenu du fichier texte

tell application "Finder"
	set Mais to (a reference to home)
	set PathFichier to file "Fichier.txt" of folder "Desktop" of Mais as alias
	-- Ouverture et lecture du fichier de travail "NomFichier.txt"
	try
		open for access PathFichier -- Ouvre le fichier en lecture
		set liste to read PathFichier -- Lecture du fichier
		close access PathFichier -- Ferme le fichier
		
		my trie()
		
		open for access PathFichier with write permission -- Ouvre le fichier en écriture
		write newList starting at 0 to PathFichier -- Ecriture a partir de la première ligne dans le fichier
		set eof PathFichier to (length of newList) -- Ecriture
		close access PathFichier -- Ferme le fichier
	on error ErrorMessage number ErrorNumber
		activate me
		display alert "Error " & (ErrorNumber as text) message ErrorMessage as warning buttons {"OK"} default button "OK"
		
		close access PathFichier -- Pour être sur que le fichier seras fermé si une erreur
	end try
	set {mem, newList, liste} to {{}, "", ""}
end tell

on trie()
	repeat with i from 1 to count paragraph of liste
		set lue to paragraph i of liste -- Ligne lue
		set theoffset to offset of ":" in lue -- Recherche la position des : dans le texte
		-- + 2 pour pas prendre en compte : et l'espace et - 1 pour finir au dernier caractère
		set verif to text (theoffset + 2) thru -1 in lue -- Trie que sur les dates
		-- -- Contrôle sur la date (samedi 13 novembre 2010 : 00:00:00)
		set theDate to date (lue as string) -- Gére mieux les erreurs 
		if mem does not contain theDate then -- Contrôle si la date a été lue
			set newList to newList & lue & return as string -- Ajout du texte lue (pas un doublon)
			set mem to mem & theDate -- Place en mémoire la date pour les tries suivants
		end if
	end repeat
end trie
```

Fait un test avec mon listing qui est plein d'erreurs de frappe.

Il est loin d'être parfait, c'est juste pour te donner ma façon de voir rapidement comment gérer ton problème.

@+


----------



## Astronight (17 Mars 2011)

ceslinstinct a dit:


> Bonsoir
> 
> Tu pose une question, et tu te répond sans nous donner le temps de réfléchir.
> 
> ...




Merci pour votre réponse, désolé mais en répondant, j'ai cru pouvoir vous aider " à avancer" dans ce script. Puisque je n'arrête pas de réfléchir des que je post le topic 

En tout cas merci! Je vais étudier votre script pour voir si il marche!


----------



## Astronight (17 Mars 2011)

Re, je n'arrive pas à faire marcher votre script.. 
J'ai essayé de le modifier mais je n'y arrive pas.

Je n'arrive pas à trouver quand vous supprimez le doublon dans votre script


Pouvez vous essayer de me l'expliquer?

Sinon, vu que mon script marche parfaitement, il ne lui manque plus que le fait de pouvoir supprimer une ligne "i"   d'un fichier texte n'auriez vous pas une solution?


----------



## ceslinstinct (17 Mars 2011)

Astronight a dit:


> Re, je n'arrive pas à faire marcher votre script..
> J'ai essayé de le modifier mais je n'y arrive pas.
> 
> 
> ...


Bonsoir

*Quel système*?

Testé avec Léopard 10.5.8 directement depuis l'éditeur de scripts et compilé en application.

Le code fait le trie par ligne et non par texte.

Lecture du fichier, écrit dans une variable les lignes qui ne sont pas des doublons.
Réécrit le fichier texte lue par le contenu de la variable.

@+


----------



## Astronight (17 Mars 2011)

Ah oué, j'aime bien votre approche différente du problème 

J'ai mac os 10.6.6, votre script marche dessus?


----------



## ceslinstinct (17 Mars 2011)

Astronight a dit:


> Ah oué, j'aime bien votre approche différente du problème
> 
> J'ai mac os 10.6.6, votre script marche dessus?



Bonsoir

Crée une signature avec modèle du Mac utilisé et surtout le système, ça évite de donner des mauvaises explications.

Marche très bien avec Léopard 10.5.8 mais pas avec Snow Léopard (je vient de tester).

Je reste en 10.5.8 pour pas a avoir à réécrire tous mes codes, j'attend Lion pour le faire.

Donc mon code pour toi, poubelle, il faut le réécrire.

@+


----------



## Astronight (17 Mars 2011)

Voila c'est fait, c'est modifié! avec une pointe d'humour geek..


----------



## ceslinstinct (17 Mars 2011)

Astronight a dit:


> Voila c'est fait, c'est modifié! avec une pointe d'humour geek..


Bonsoir

Signature     

Snow Léopard, regarde ma signature.

Je refait le code pour voir ce qui cloche avec ce code (je le sais, certaines gestions sont différentes).

@+


----------



## Astronight (17 Mars 2011)

ceslinstinct a dit:


> Bonsoir
> 
> Signature
> 
> ...




Ah oui, Snow leopard pour vérifier la compatibilité, je n'avais pas fait attention :x

Merci pour vous intéresser à ce code sur Snow Leopard !


----------



## ceslinstinct (17 Mars 2011)

Astronight a dit:


> Ah oui, Snow leopard pour vérifier la compatibilité, je n'avais pas fait attention :x
> 
> Merci pour vous intéresser à ce code sur Snow Leopard !



Ce que je voudrais savoir:

Dans le post 1 c"est des dates a trier, et dans le post 2 c'est des eMails (c'est pas la même façon de trie).

@+


----------



## Astronight (17 Mars 2011)

ceslinstinct a dit:


> Ce que je voudrais savoir:
> 
> Dans le post 1 c"est des dates a trier, et dans le post 2 c'est des eMails (c'est pas la même façon de trie).
> 
> @+



Non en faite les Adresseemail c'était juste car j'ai piqué le code d'un autre site et je l'ai modifié sans changer le nom des variables 

Sinon, ce qui doit changer c'est seulement 	set AppleScript's text item delimiters to {":"}   non?
Le vrai script et donc le second membre  s'ecrit sous la forme : 
Pomme : Banane
Triangle : Banane

(ce n'est pas forcément des dates)


----------



## Anonyme (18 Mars 2011)

Bonjour,


Astronight a dit:


> Non en faite les Adresseemail c'était juste car j'ai piqué le code d'un autre site et je l'ai modifié sans changer le nom des variables


J'ai regardé le script de ton deuxième message,

```
set emailAddress to text item 1 of someText
----
set emailAddress1 to text item 2 of someText
```
 tu compares l'élément dans la première colonne d'une ligne avec un élément de la deuxième colonne de la ligne suivante.

Voici le script qui supprime les lignes si l'élément de la deuxième colonne  est un doublon qui se suit.
Exemple, si pomme est dans deuxième colonne des lignes 3 à 9, les lignes 4 à 9 seront supprimées.

```
set PathFichier to ((path to desktop as string) & "Fichier.txt") as alias
set ListeLigne to paragraphs of (read PathFichier)

set {i, oldTID, newText, t_count} to {1, text item delimiters, item 1 of ListeLigne, count ListeLigne}
set text item delimiters to {":"}
set endLine to character id 10 -- ou return si Mac au lieu de Unix

repeat while i < t_count
	set someText to item i of ListeLigne
	set t_item2 to text item 2 of someText
	repeat with k from (i + 1) to t_count
		if text item 2 of (item k of ListeLigne) is not t_item2 then
			if i > 1 then set newText to newText & endLine & someText
			if k = t_count then set newText to newText & endLine & (last item of ListeLigne)
			exit repeat
		end if
	end repeat
	set i to k
end repeat
set text item delimiters to oldTID
my write_to_file(PathFichier, newText)

on write_to_file(f, t_data)
	try
		set openfile to open for access f with write permission
		set eof openfile to 0
		write t_data to openfile
		close access openfile
	on error err
		try
			close access f
		end try
		display alert err
	end try
end write_to_file
```
Si vous voulez comparer la premiére colonne avec la deuxième colonne de la ligne suivante : remplacer 
set t_item2 to text item 2 of someText par set t_item2 to text item 1 of someText.
Ajuster  le text item delimiters par *{" : "}* s'il y a des espaces avant et après le :, sinon la comparaison ne fonctionnera pas, parce que l'élément dans la première colonne  a un espace après, l'élément dans la deuxième colonne a un espace avant.


Voici le script qui supprime les lignes si l'élément de la deuxième colonne  est un doublon. (ce n'est pas obligatoire d'être dans la ligne suivante).
Exemple, si *pomme* est dans deuxième colonne de la deuxième ligne  et dans la deuxième colonne de la dixième ligne ,(*pomme* n'est pas dans les lignes 4 à 9), la dixième ligne sera supprimé.
Donc, aucun doublon dans la deuxième colonne

```
set PathFichier to ((path to desktop as string) & "Fichier.txt") as alias
set ListeLigne to paragraphs of (read PathFichier)

set {i, oldTID, newText, t_count, L} to {1, text item delimiters, "", count ListeLigne, {}}
set text item delimiters to {":"}
set endLine to character id 10 -- ou return si Mac au lieu de Unix

repeat with i from 1 to t_count
	set t_item2 to text item 2 of item i of ListeLigne
	if t_item2 is not in L then
		set end of L to t_item2
		if i < t_count then
			set newText to newText & item i of ListeLigne & endLine
		else
			set newText to newText & item i of ListeLigne
		end if
	end if
end repeat

set text item delimiters to oldTID
my write_to_file(PathFichier, newText)

-- ajoute la fonction on write_to_file(f, t_data) de mon premier script
```


----------



## Astronight (18 Mars 2011)

Mac_Jac a dit:


> Bonjour,
> 
> 
> Voici le script qui supprime les lignes si l'élément de la deuxième colonne  est un doublon. (ce n'est pas obligatoire d'être dans la ligne suivante).
> ...



Bonsoir! Merci beaucoup, j'ai testé ce script il marche parfaitement ! 

J'ai juste un peu soucis.. pas trop en relation avec le script, mais il se peut que des fois j'ai deux lignes à la fin vide, c'est à dire des entrées.
par ex voila mon fichier : " Pomme : XX
Banane : XX
Ecole : xx 

                       "

Donc il y'a un beug et l'applescript me dis impossible de récupérer text item 2 of ""
Y'a-t-il un moyen pour que je lui dise de ne pas examiner ces dernieres lignes si celle ci ne continenent rien?

Ps : j'ai essayé de rajouter ce script au début de la boucle c'est à dire avant cette ligne 

```
set t_item2 to text item 2 of item i of ListeLigne
```
mais le code ne veux pas marcher! 



```
set witem to item (t_count-1) of ListeLigne
	if (witem = "") and ( i = (t_count-1)) then
		exit repeat
	end if
set zitem to item t_count of ListeLigne
	if (zitem = "") and (i= t_count) then
		exit repeat
	end if
```
Merci!


----------



## ceslinstinct (18 Mars 2011)

Astronight a dit:


> Bonsoir! Merci beaucoup, j'ai testé ce script il marche parfaitement !



Bonsoir

Teste ce code qui prend en charge les lignes vides.


```
-- Testé avec Snow Léopard 10.6.6 & Léopard 10.5.8

set mem to {} as list -- Mémoire des textes lues
set newList to "" -- Nouveau listing

tell application "Finder"
	-- Chemin du fichier texte
	set PathFichier to (((path to desktop as string) & "Fichier.txt") as string) as alias
	set ContenuFic to read PathFichier -- Lecture du fichier texte
	
	set {od, AppleScript's text item delimiters} to {AppleScript's text item delimiters, ":"}
	
	repeat with i from 1 to (count paragraph of ContenuFic)
		set lue to paragraph i of ContenuFic -- Ligne lue
		try -- Pour ne pas prendre en compte les lignes vides
			set verif to (item 2 of text items of (lue as string)) -- Texte à contrôler
			
			if mem does not contain verif then -- Si le texte lue n'est pas dans la variable mem
				set newList to newList & lue & return as string -- Ajout du texte lue (pas un doublon)
				set mem to mem & verif -- Place en mémoire le texte lue pour les tries suivants
			end if
		end try
	end repeat
	
	set AppleScript's text item delimiters to od
	
	try
		open for access PathFichier with write permission -- Ouvre le fichier en écriture
		-- Ecriture  à partir de la première ligne (supprime l'ancien contenu)
		write newList starting at 0 to PathFichier
		set eof PathFichier to (length of newList) -- Ecriture
		close access PathFichier -- Ferme le fichier
	on error
		close access PathFichier -- Pour être sur que le fichier seras fermé si une erreur
	end try
end tell

tell me to activate
display dialog "Trie terminé" buttons {"Ok"} default button "Ok" with title "TRIE FICHIER" giving up after 2
```

@+


----------



## Anonyme (18 Mars 2011)

Bonsoir,



Astronight a dit:


> Bonsoir! Merci beaucoup, j'ai testé ce script il marche parfaitement !
> 
> J'ai juste un peu soucis.. pas trop en relation avec le script, mais il se peut que des fois j'ai deux lignes à la fin vide, c'est à dire des entrées.


Oui c'est possible.
Autre erreur possible, c'est qu'une ligne ne contient pas de :
Voici le repeat qui gère les deux cas.
Les lignes vides ne seront pas ajoutés au fichier.

```
repeat while i < t_count
	set someText to item i of ListeLigne
	if ":" is in someText then
		set t_item2 to text item 2 of someText
		repeat with k from (i + 1) to t_count
			if text item 2 of (item k of ListeLigne) is not t_item2 then
				if i > 1 then set newText to newText & endLine & someText
				if k = t_count then set newText to newText & endLine & (last item of ListeLigne)
				exit repeat
			end if
		end repeat
		set i to k
	else
		if i > 1 and someText is not "" then set newText to newText & endLine & someText
		set i to i + 1
	end if
end repeat
```


----------



## Astronight (18 Mars 2011)

@Mac_Jac
@ceslinstinct

Merci infiniment à vous deux, mon script est prêt  

Passage en mode résolu!


----------

