Récupérer une ligne d'un fichier selon un terme précis. [Résolu]

Signaler
Messages postés
3178
Date d'inscription
lundi 11 novembre 2013
Statut
Membre
Dernière intervention
11 octobre 2020
-
Messages postés
14854
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
11 octobre 2020
-
Bonjour à toutes et à tous.

J'ai en ma possession un fichier...

Je dois récupérer une ligne qui comporte ce(s) terme(s) : "body":"


Voici un script qui fonctionne, qui détecte la ligne, mais qui ne me l'affiche pas....

j'ai peut-être une idée de "pourquoi il trouve la ligne sans l'afficher avec echo".


Voici le script en question :
Dim objFile, strLine,ligne

fichier = "fichier.txt"

T1 = "body" & Chr(34) & ":" & Chr(34)

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.openTextFile(fichier, 1, false)


Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile= objFSO.OpenTextFile(fichier, 1)
Do While Not objFile.AtEndOfStream
strLine = objFile.ReadLine
If InStr(1, strLine, T1) <> 0 Then
WScript.Echo "Ligne trouvée"
ligne = strLine
End If

Loop
objFile.Close

WScript.Echo ligne
WScript.Echo "FIN"



Mon hypothèse : la longueur monstrueuse de la ligne en question.


Est-ce que "echo" a une limitation de caractères ?



pouvez-vous m'aider ?

Merci :D


++



10 réponses

Messages postés
14854
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
11 octobre 2020
444
Bonjour

tout d'abord, voici un petit tuto sur la bonne utilisation des balises de code https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code

Ensuite, je ne fais pas de VBS, cela dit:
  • As tu essayé avec un fichier bidon dont la ligne est plus courte?
  • Ce script n'affichera qu'une ligne même s'il y en a plusieurs
  • Ce script ira jusqu'au bout du fichier, même si ça fait "longtemps" qu'il a trouvé une ligne correspondante
  • Au final, as tu besoin de la ligne entière ou seulement d'un morceau?
  • Connais tu les regex?

Messages postés
3178
Date d'inscription
lundi 11 novembre 2013
Statut
Membre
Dernière intervention
11 octobre 2020

Salut.

« As tu essayé avec un fichier bidon dont la ligne est plus courte? »
=> En effet, tu as vu juste, j'ai créé un fichier bidon avec plusieurs lignes, dont une comportant le terme souhaité.

Et j'arrive à l'afficher.

« Ce script n'affichera qu'une ligne même s'il y en a plusieurs »
« Ce script ira jusqu'au bout du fichier, même si ça fait "longtemps" qu'il a trouvé une ligne correspondante »
=> Ce terme n’apparaît qu'une fois, donc une seule ligne.

Je pourrais donc fermer la boucle s'il la trouve.

« Au final, as tu besoin de la ligne entière ou seulement d'un morceau? »
En fait, celle ligne contient plusieurs morceaux, que je souhaite récupérer.

Et le terme recherché, est le seul à être "unique".

En résumé :
  • Je trouve la ligne correspondante
  • Je l'exploite


« Connais tu les regex? »
Je connais que de nom, et je n'ai pas envie de les connaitre...


Les morceaux à récupérer, sont entre des caractères / termes qui ne changent jamais.
Donc pour mon cas, je préfère éviter les regex.



reste le problème de la ligne "trop longue".


Je vais potasser ^^


Merci encore de ta réponse.


EDIT :
Je vais surement devoir remplacer ce terme par le même terme, précédé d'un saute de ligne.
Et un terme à la fin de la ligne, pareil.

Je pense que la longueur de la ligne sera largement réduite.

++

Comme un sage m'a dit : « en France, on a le droit de tout faire....
Faut juste ne pas se faire choper. »
Messages postés
14854
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
11 octobre 2020
444
Donc pour mon cas, je préfère éviter les regex.

Pourtant tout ce que tu as décrit est un cas d’école pour une regex.

Tu lui donnes le fichier entier, et elle te retourne directement les morceaux dont tu as besoin via une capture et des sous captures.

Si tu souhaites rester avec ta recherche ligne par ligne, je ne peux pas t’aider.
Si tu souhaites tester la regex alors, peux tu poster une ligne exemple et décrire quels morceaux extraire?
Messages postés
3178
Date d'inscription
lundi 11 novembre 2013
Statut
Membre
Dernière intervention
11 octobre 2020

Salut

Faire du regex sur une ligne à "rallonge", je ne vois pas comment tu puisses faire....

Regarde la ligne (je suis passé par pastebin, elle passe pas ici)

https://pastebin.com/QHnYbcLc



Je cherche donc à récupérer ce qu'il y a :
- Entre "subject":" et ","body":"
- Entre ","body":" et ","ad_type"


++


Comme un sage m'a dit : « en France, on a le droit de tout faire....
Faut juste ne pas se faire choper. »
Messages postés
14854
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
11 octobre 2020
444
Effectivement c'est une très grande ligne.

Voici un premier jet de regex
"subject":"(.*)","body":"(.*)","ad_type"


Voir cet exemple https://regex101.com/r/WIDSI5/1
Au milieu de la colonne de droite, tu peux voir la capture complète, le groupe 1 et le groupe 2

Cette partie de la syntaxe
"subject":"
veut dire que la capture commence littéralement par
"subject":"

Les parenthèses définissent le début et la fin d'un groupe.
Le point veut dire que n'importe quel caractère est accepté.
L'étoile signifie répété "indéfiniment" (enfin jusqu'à l'arrivée de la suite de la syntaxe)
Donc
"subject":"(.*)","body":"
signifie que la capture complète commence par
"subject":"
et fini par
","body":"
et que tout ce qui est entre les 2 sera mis dans le groupe 1.

Idem pour le groupe 2.


Comme je l'ai dit, je n'ai jamais fait de VBS, mais c'est proche de VBA.
Alors voilà une petite macro qui fonctionne, j'ai mis ta ligne dans le fichier Test.Txt, j'ai ajouté quelques lignes avant et aussi après.

Tu peux le télécharger là https://www.cjoint.com/c/JJdsD0aw1n1


Sub TestRegex()
    Dim reg As VBScript_RegExp_55.RegExp
    Dim Match As VBScript_RegExp_55.Match
    Dim Matches As VBScript_RegExp_55.MatchCollection

    ' instanciation
    Set reg = New VBScript_RegExp_55.RegExp

    reg.Pattern = """subject"":""(.*)"",""body"":""(.*)"",""ad_type"""
    
    Dim toutLeTexte As String
    toutLeTexte = LireFichierTexte("C:\Temp\Test.txt")
    
    Set Matches = reg.Execute(toutLeTexte)
    For Each Match In Matches
        Debug.Print "source >>", Match.Value
        For i = 0 To Match.SubMatches.Count - 1
            Debug.Print "[$" & i + 1 & "]", Match.SubMatches(i)
        Next i
    Next Match
End Sub


Public Function LireFichierTexte(ByVal MonFichier As String) As String
    'https://excel-malin.com/codes-sources-vba/vba-lire-contenu-de-fichier-texte/
    On Error GoTo LireFichierTexteErreur
    Dim IndexFichier As Integer
    IndexFichier = FreeFile()
    Open MonFichier For Binary Access Read As #IndexFichier
    LireFichierTexte = Space$(LOF(IndexFichier))
    Get #IndexFichier, , LireFichierTexte
    Close #IndexFichier
    
    Exit Function
LireFichierTexteErreur:
    Close #IndexFichier
    LireFichierTexte = ""
End Function


Comme tu peux le constater sur la capture d'écran si dessous, y'a juste un petit soucis d'UTF à régler, mais sinon, ça extrait bien ce que tu veux


Quand j'étais petit, la mer Morte n'était que malade.
George Burns
Messages postés
3178
Date d'inscription
lundi 11 novembre 2013
Statut
Membre
Dernière intervention
11 octobre 2020

Salut et merci de ton savoir ;)


Cependant, je ne sais pas pourquoi, mais j'ai vraiment du mal avec les regex. :/


Du coup, vu que mon pote m'a fait parler de VBNet, j'ai voulu sauté le pas.

Et j'ai réussi ce que je voulais faire.

Imports System
Imports System.Text.RegularExpressions
Imports System.IO

Module Program2



    Sub Main2(args As String())

        ' ","subject":"
        ' ","body":"
        ' ","ad_type":"

        ' ma ligne : message1","subject":"message2","body":"message3","ad_type":"message4

        ' Je souhaite donc récupérer ce qu'il a entre : ,"subject":" et ","body":"
        ' Je souhaite donc récupérer ce qu'il a entre : ","body":" et ","ad_type":"

        ' En résumé, je veux récupérer message1 et message2

        Dim Term1 As String = Chr(34) & "," & Chr(34) & "subject" & Chr(34) & ":" & Chr(34)
        Dim Term2 As String = Chr(34) & "," & Chr(34) & "body" & Chr(34) & ":" & Chr(34)
        Dim Term3 As String = Chr(34) & "," & Chr(34) & "ad_type" & Chr(34) & ":" & Chr(34)


        Dim fichiertest = "c:\users\tomce\desktop\test.txt"
        Dim lines() As String = IO.File.ReadAllLines(fichiertest)
        Dim ligne = lines(0)
        Console.WriteLine(ligne)

        Dim debut_t As Integer = ligne.IndexOf(Term1)
        Dim fin_t As Integer = ligne.IndexOf(Term2)
        Dim debut_d As Integer = ligne.IndexOf(Term2)
        Dim fin_d As Integer = ligne.IndexOf(Term3)

        Dim tr As String = Strings.Mid(ligne, debut_t + Term1.Length + 1, fin_t - debut_t - Term1.Length)
        Dim dc As String = Strings.Mid(ligne, debut_d + Term2.Length + 1, fin_d - debut_d - Term2.Length)
        Console.WriteLine(tr)
        Console.WriteLine(dc)

        System.Threading.Thread.Sleep(3000)


    End Sub

End Module


Je récupère bien message1 et message2



J'ai testé sur la ligne que j'avais dès le départ : avec VBNet, pas d'erreur de longueur de ligne.


Du coup, c'est résolu.



++
Messages postés
14854
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
11 octobre 2020
444
Bonjour


Ce code ne fonctionne que s’il n’y a que ta ligne dans le fichier.


A la fin, à la place de
System.Threading.Thread.Sleep(3000)


Console.ReadLine()


Comme ça la console se fermera quand tu auras tapé entrée.


Ps, c’est encore plus simple d’utiliser les regex en .Net
Messages postés
14854
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
11 octobre 2020
444
Voilà ce que ça donne

Imports System.IO
Imports System.Text.RegularExpressions

Module Module1

    Sub Main()
        Dim fichierComplet As String = File.ReadAllText("C:\Temp\Test.txt")
        Dim pattern As String = """subject"":""(?<sujet>.*)"",""body"":""(?<corps>.*)"",""ad_type""" 'le moteur de regex de .Net accpete les groupes avec des noms, ici "sujet" et "corps"

        For Each m As Match In Regex.Matches(fichierComplet, pattern)
            If m.Success Then
                Console.WriteLine("Le sujet: {0}", m.Groups("sujet").Value)
                Console.WriteLine("Le corps: {0}", m.Groups("corps").Value)
            End If
        Next

        Console.ReadLine()
    End Sub

End Module





PS je te conseille de lire ce petit article https://codes-sources.commentcamarche.net/faq/11151-pourquoi-mon-code-vb6-vba-ne-marche-pas-en-vb-net
Messages postés
3178
Date d'inscription
lundi 11 novembre 2013
Statut
Membre
Dernière intervention
11 octobre 2020

Salut.

Et merci, je comprends mieux.


Je passe en résolu ;)


++
Messages postés
14854
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
11 octobre 2020
444
de rien