Question Comparaison de chaines de caractères (Résolu)

Plus d'informations
il y a 16 ans 5 mois #1133 par pgu
Réponse de pgu sur le sujet Re:Comparaison de chaine de caratères
J'ai repris le dernier script, mais il n'apréci pas les lignes vides.
j'ai donc modifié la partie \"compare-object\" par cette partie de code:

[code:1]
...
# Comptage du nombre de caractères différents:
if (($line1.length -gt 0 ) -and ($line2.length -gt 0)){
$diff += (compare-object ([char[]]$line1) ([char[]]$line2) | measure-object).count
}
else{
if (($line1.length -eq 0 ) -and ($line2.length -gt 0)) { $diff += $line2.length }
if (($line2.length -eq 0 ) -and ($line1.length -gt 0)) { $diff += $line1.length } }
}
}
...
[/code:1]

Je ne suis pas certain que ce soit le plus optimisé, mais cela permet de passer la problématique des lignes vides.

mais mon problème principale c'est que ce script ne me retourne pas le bon résultat.
Pour tester, j'ai dupliqué mon fichier référence, et j'ai inséré 3 erreurs sur deux lignes différentes (lignes 2083 et 2098).
j'ai join ces deux fichiers à cette note.


Je m'attends donc a avoir comme résultat la valeur 3 (le systeme me retourne 6).

Mais là je sèche...

fichiers tests :

La pièce jointe Filetocompare.zip est absente ou indisponible

Pièces jointes :

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 16 ans 5 mois #1136 par Jacques Barathon
Ah oui, grosse erreur de ma part. J'aurais dû remarquer ça dans mes tests.

En fait, compare-object retourne tous les caractères différents, mais il le fait pour les deux lignes. Par exemple:

[code:1]
$ref = \"bonsoir\"
$dif = \"bonjour\"
compare-object ([char[]]$ref) ([char[]]$dif)
InputObject SideIndicator

j =>
u =>
s <=
i <=[/code:1]
On a, logiquement, le j et le u qui sont dans $dif mais pas dans $ref, et le s et le i qui sont dans $ref et pas dans $dif.

Soit, au total, 4 différences pour compare-object, même si pour nous il n'y a que deux caractères de différents.

Je viens de passer cinq minutes à essayer de faire \"cracher\" le bon chiffre à compare-object, mais ça ne semble pas vraiment faisable (en tout cas pas facilement). Je crois donc qu'il faudra revenir à un algorithme plus traditionnel.

Je travaille là-dessus, je reviens vers toi dans l'après-midi.

Janel

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 16 ans 5 mois #1137 par pgu
Réponse de pgu sur le sujet Re:Comparaison de chaine de caratères
ok pour l'explication, mais dans ce cas, il suffirait de diviser par 2 le résultat du \"compare-object\"

... j'ai dis une bétise là ? :huh:

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 16 ans 5 mois #1138 par Jacques Barathon
Oui, c'est une grosse bêtise, enfin presque ;)

Fais la comparaison en ayant des lignes de longueur différente, et tu verras que ça ne marche pas.

Evidemment, on pourrait tester si les lignes sont de même taille: si oui faire une division par deux, et sinon... sinon quoi? Il faudrait retirer au nombre retourné par compare-object le nombre de caractères qui dépassent, puis diviser le reste par deux. Faisable, en effet.

Toujours est-il que j'ai pris une approche un peu différente, mais qui repose quand même sur compare-object. J'utilise son paramètre -includeEqual pour compter le nombre de caractères que les deux lignes ont en commun, et je retire ce nombre de la longueur de la ligne la plus longue.

Voici donc la version corrigée. Au passage j'ai ajouté un paramètre -verbose pour afficher les lignes différentes si l'on veut vérifier ce qui se passe.

[code:1]
param (
$reference,
$difference,
[switch]$verbose
)

# Ouverture des deux fichiers:

$file1 = [System.IO.File]::OpenText((dir $reference))
$file2 = [System.IO.File]::OpenText((dir $difference))

# initialisation du compteur de caractères différents:

$totaldiff = 0

# Parcours des deux fichiers jusqu'à la fin de l'un de deux:

while (!$file1.EndOfStream -and !$file2.EndOfStream)
{
# Lecture des deux lignes en cours:

$line1 = $file1.ReadLine()
$line2 = $file2.ReadLine()

# Comptage du nombre de caractères différents:

$length = $(if ($line1.length -gt $line2.length) { $line1.length } else { $line2.length })
$equal = (compare-object ([char[]]$line1) ([char[]]$line2) -include | where {$_.SideIndicator -eq \"==\"} | measure-object).count
$localdiff = $length - $equal
if ($localdiff -and $verbose) {
\"$localdiff character{0} different:`n-- $reference`n$line1`n--$difference`n$line2`n \" -f $(if ($localdiff -gt 1) {\"s\"})

}
$totaldiff += $localdiff
}

# Ajout du nombre de caractères restants dans le fichier le plus long:

$remainder = \"\"
if ($file1.EndOfStream -and !$file2.EndOfStream) { $remainder = $file2.ReadToEnd(); $remainfile = $difference }
if ($file2.EndOfStream -and !$file1.EndOfStream) { $remainder = $file1.ReadToEnd(); $remainfile = $reference }
if ($remainder) {
$remaindiff = 0
$remainder.Split(\"`r`n\"«») | foreach { $remaindiff += $_.Length }
if ($verbose) { \"$remaindiff more character{0} at the end of ${remainfile}:`n$remainder`n \" -f $(if ($remaindiff -gt 1) {\"s\"})}
$totaldiff += $remaindiff
}

# Fermeture des fichiers:

$file1.Close()
$file2.Close()

# Et pour finir, on retourne le nombre total de caractères différents:

if ($verbose) { \"Total number of differences: $totaldiff\" }
else { $totaldiff }[/code:1]
C'est pas super compact, mais là comme ça je n'ai pas trouvé mieux. On peut sans doute optimiser, j'attends ton retour après un test sur les gros fichiers dont tu parlais.

Janel

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 16 ans 5 mois #1142 par pgu
Réponse de pgu sur le sujet Re:Comparaison de chaine de caratères
ok pour la bêtise... il va falloir que je change de cerveau !

J'avoue que la concaténation de commande me donne toujours un peut mal à la tête !

Avec ton script, je retombe sur mes problèmes de lignes vides

Voici le message d'errreur que j'ai pour chaque ligne vide:

+ $equal = (compare-object <<<< ([char[]]$line1) ([char[]]$line2) -include
| where {$_.SideIndicator -eq \"==\"} | measure-object).count
Compare-Object : Impossible de lier l'argument au paramètre « ReferenceObject »
, car il s'agit d'un tableau vide.
Au niveau de C:\SERVEURS\Powershell\compfileout.ps1 : 28 Caractère : 29

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 16 ans 5 mois #1146 par Jacques Barathon
Bigre, je me suis encore fait avoir par la version de PowerShell que je teste sur mon PC... En testant sur un poste équipé de la v1, je tombe sur le même problème que toi.

Voici une version corrigée, qui se contente de faire un test sur la longueur de la ligne:

[code:1]
param (
$reference,
$difference,
[switch]$verbose
)

# Ouverture des deux fichiers:

$file1 = [System.IO.File]::OpenText((dir $reference))
$file2 = [System.IO.File]::OpenText((dir $difference))

# initialisation du compteur de caractères différents:

$totaldiff = 0

# Parcours des deux fichiers jusqu'à la fin de l'un de deux:

while (!$file1.EndOfStream -and !$file2.EndOfStream)
{
# Lecture des deux lignes en cours:

$line1 = $file1.ReadLine()
$line2 = $file2.ReadLine()

# Comptage du nombre de caractères différents:

if ($line1.length -eq 0 -or $line2.length -eq 0) {
$localdiff = $line1.length + $line2.length
if ($line1.length -ne $line2.length -and $verbose) {
\"$localdiff character{0} different:`n-- $reference`n$line1`n--$difference`n$line2`n \" -f $(if ($localdiff -gt 1) {\"s\"})
}
$totaldiff += $localdiff
}
else {
$length = $(if ($line1.length -gt $line2.length) { $line1.length } else { $line2.length })
$equal = (compare-object ([char[]]$line1) ([char[]]$line2) -include | where {$_.SideIndicator -eq \"==\"} | measure-object).count
$localdiff = $length - $equal
if ($localdiff -and $verbose) {
\"$localdiff character{0} different:`n-- $reference`n$line1`n--$difference`n$line2`n \" -f $(if ($localdiff -gt 1) {\"s\"})
}
$totaldiff += $localdiff
}
}

# Ajout du nombre de caractères restants dans le fichier le plus long:

$remainder = \"\"
if ($file1.EndOfStream -and !$file2.EndOfStream) { $remainder = $file2.ReadToEnd(); $remainfile = $difference }
if ($file2.EndOfStream -and !$file1.EndOfStream) { $remainder = $file1.ReadToEnd(); $remainfile = $reference }
if ($remainder) {
$remaindiff = 0
$remainder.Split(\"`r`n\"«») | foreach { $remaindiff += $_.Length }
if ($verbose) { \"$remaindiff more character{0} at the end of ${remainfile}:`n$remainder`n \" -f $(if ($remaindiff -gt 1) {\"s\"})}
$totaldiff += $remaindiff
}

# Fermeture des fichiers:

$file1.Close()
$file2.Close()

# Et pour finir, on retourne le nombre total de caractères différents:

if ($verbose) { \"Total number of differences: $totaldiff\" }
else { $totaldiff }[/code:1]

Là, ça devrait marcher mais j'avoue ne pas avoir testé avec beaucoup de fichiers. Dis-moi si tu constates d'autres problèmes.

Janel

PS. Edité pour corriger un autre bug + galères de publication sur le forum avec les tags de code...

Message édité par: janel, à: 13/10/07 12:35<br><br>Message édité par: Arnaud, à: 13/10/07 15:26

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.098 secondes
Propulsé par Kunena