Risultati da 1 a 9 di 9

Discussione: Espressioni regolari RegexOptions.SingleLine



  1. #1
    L'avatar di dracoscrigno
    Clicca e Apri
    Data Registrazione
    May 2016
    Località
    ferrara
    Età
    41
    Messaggi
    1741
    Versione Office
    office pro 2010
    Likes ricevuti
    374
    Likes dati
    206

    Espressioni regolari RegexOptions.SingleLine

    Dopo aver fatto ridere tutta la comunità con questo post nel thread aperto da scossa: QUIZ (difficilino) del ConcaSomma (concatena e/o somma), correggendo l' espressione che determina la stringa in uscita di modo che potesse eliminare un separatore di parola all' inizio ed alla fine di una frase come fa il TRIM() per gli spazi in VBA, ho incontrato un problema che non riesco a risolvere.

    Come si vede dal file allegato, il pattern sembra andare bene per tutte le occorrenze purchè queste non contengano dei "ritorno a capo"

    nello specifico;

    Presa una frase ad esempio come:

    "*****Io*sono*una*frase*senza*ritorno*a*capo****"

    il risultato è corretto èd è:
    "Io*sono*una*frase*senza*ritorno*a*capo"

    Ma se la frase di esempio contiene ritorni a capo come:

    "*****Io*sono*una*frase*
    con*un*ritorno*a*capo****"

    il risultato uscente e non corretto sarà: "Io*sono*una*frase*"


    Di fatto vengono trovate più occorrenze, una per ogni "ritorno a capo"

    Da un lato potrei risolvere la cosa concatenando tutte le occorrenze trovate nel matches dell' espressione regolare ma vorrei capire qual' è il metodo per dire al motore di non considerare il carattere di ritorno a capo e trattare tutta la stringa come se fosse su un unica linea.


    l' area di test per la ricerca del pattern è questa pagina: regexpal.com

    La frase utilizzata per la stesura dell' espressione:
    Codice: 
    *******In*questa,*invece,************
    ******vado*a*capo*io*sette,***********
    otto*volte.*Vediamo*un*po…*****************
    **************Mi*servirà*impostare*******************
    la*prorietà*multi*line*sicuramente**************************
    *****************ed*aggiungere*il*ritorno*a*capo*nel*pattern***************
    Il pattern, presumibilmente corretto: ([^.*])(.+)([^*])

    Il pattern vorrebbe intendere:
    (Non cominciare con un asterisco)(va bene qualsiasi carattere preso una o più volte)(non terminare con un asterisco)

    Nella pagina è possibile flaggare l' opzione Dot matches all con la quale si dice al motore che con il punto si tiene conto anche del ritorno a capo. con questa opzione flaggata, il risultato è corretto.
    Purtroppo non riesco a capire come impostare questa cosa in VBA
    File Allegati File Allegati
    Ultima modifica fatta da:dracoscrigno; 28/09/16 alle 23:16 Motivo: mancava l' allegato

  2. #2
    L'avatar di Anthony
    Clicca e Apri
    Data Registrazione
    Sep 2016
    Località
    Ivrea (TO)
    Messaggi
    499
    Versione Office
    2003-2010-2016
    Likes ricevuti
    298
    Likes dati
    39

    Re: Espressioni regolari RegexOptions.SingleLine

    Tutte le volte che cerco di capire una regular expression mi viene mal di testa; questo caso non ha fatto eccezione, ma ho limitato i danni limitandomi a "guardare senza voler capire troppo".
    Ora, secondo me, bisognerebbe capire come modificare quell' Item(0) affinche' diventi Item(all).
    In attesa, suggerisco di eliminare tutti i LineFeed presenti eventalmente nella stringa iniziale, lavorare questa stringa, ripristinare infine i LineFeed; cose che ho ottenuto con le due linee fuori posizione aggiunte nel tuo codice:
    Codice: 
    Function Tlim_2(ByVal sString As String, Optional sSep As String = " ") As String
     'by Draco
     '2016-09-27
        Dim EspressioneRegolare As Object
        Set EspressioneRegolare = CreateObject("VBScript.RegExp")
    sString = Replace(sString, Chr(10), "Z#cZc#", , , vbBinaryCompare)
        With EspressioneRegolare
            .Global = True
            .MultiLine = False
            .Pattern = "([^" & sSep & "])(.+)([^" & sSep & "?])"
            If .test(sString) Then
                Tlim_2 = .Execute(sString).Item(0)
    Tlim_2 = Replace(Tlim_2, "Z#cZc#", Chr(10), , , vbBinaryCompare)
            End If
        End With
        Set EspressioneRegolare = Nothing
    End Function
    Ciao

  3. #3
    L'avatar di dracoscrigno
    Clicca e Apri
    Data Registrazione
    May 2016
    Località
    ferrara
    Età
    41
    Messaggi
    1741
    Versione Office
    office pro 2010
    Likes ricevuti
    374
    Likes dati
    206

    Re: Espressioni regolari RegexOptions.SingleLine

    Ciao Entony. Si. la strada del replace è attuabile ed il risutlato è valido ma non si risolve il dilemma

    Come trattare, in VBA Quello che in VB.Net è:

    Enumerazione RegexOptions

    Singleline Specifica la modalità a riga singola.Modifica il significato del punto (.) in modo che corrisponda a ogni carattere (anziché a ogni carattere eccetto \n).Per altre informazioni, vedere la sezione "Modalità a riga singola" nell'argomento Regular Expression Options.

    e nella pagina di test
    è un semplice flag dalla dicitura "Dot matches all" ?

    Faccio fatica a credere che in VBA non ci sia il modo di escludere il VbCrLf. Sono più propenso a pensare che sbaglio qualcosa.

    Rieditando

    Forse un file più ordinato è meglio di quello proposto in topic.

    Mi son anche accorto che l espressione postata non è quella utilizzata nel file. Tra l' altro non è corretta.
    Questa è quella che vine utilizzata:
    ([^*])(.+)([^*?])

    Scusatemi
    File Allegati File Allegati
    Ultima modifica fatta da:dracoscrigno; 29/09/16 alle 11:09 Motivo: formato tabella a grid

  4. #4
    L'avatar di dracoscrigno
    Clicca e Apri
    Data Registrazione
    May 2016
    Località
    ferrara
    Età
    41
    Messaggi
    1741
    Versione Office
    office pro 2010
    Likes ricevuti
    374
    Likes dati
    206

    Re: Espressioni regolari RegexOptions.SingleLine

    Citazione Originariamente Scritto da Anthony Visualizza Messaggio
    ...
    Ora, secondo me, bisognerebbe capire come modificare quell' Item(0) affinche' diventi Item(all)...
    Per concatenare tutti gli item basta ciclarli tutti.
    Solo che, come si vede anche nel risultato finale, utilizzando questo approcio, bisogna mettere anche mano al pattern perchè i risultati non sono comunque giusti.
    Tra i due è certamente meglio l' accrocchio replace dell' accrocchio item(all)


    VEdiamo se qualche lampo di genio viene sprigionato da qualche mente :)

  5. #5

    L'avatar di scossa
    Clicca e Apri
    Data Registrazione
    Jul 2015
    Località
    Verona Provincia
    Età
    57
    Messaggi
    980
    Versione Office
    .
    Likes ricevuti
    322
    Likes dati
    0

    Re: Espressioni regolari RegexOptions.SingleLine

    Premesso che quando nella cella vai a capo inserisci un carattere LF (e non CR+LF), ho "sistemato" il tuo codice:
    Codice: 
    Function Tlim_2(ByVal sString As String, Optional ByVal sSep As String = " ", Optional ByVal sLF As String = "§") As String
     'by Draco
     '2016-09-27
     'revision by scossa
     '2016-09-29
        Dim EspressioneRegolare As Object
        Dim oMatch As Object
        Dim oMatches As Object
        Dim sPattern As String
        Set EspressioneRegolare = CreateObject("VBScript.RegExp")
        
        sPattern = "[^" & sSep & "](.+)[^" & sSep & "]"
        sString = Replace(sString, vbLf, sLF, compare:=vbBinaryCompare)
        With EspressioneRegolare
            .Global = True
            .MultiLine = False
            .Pattern = sPattern
            Debug.Print .Pattern
            If .test(sString) Then
              Set oMatches = .Execute(sString)
              For Each oMatch In oMatches
                Tlim_2 = Tlim_2 & oMatch.Value
              Next
            End If
        End With
        Tlim_2 = Replace(Tlim_2, sLF, vbLf, compare:=vbBinaryCompare)
        Set EspressioneRegolare = Nothing
        Set oMatches = Nothing
    End Function
    Ho aggiunto il parametro opzionale per marcare il LF in modo da poter evitare ambiguità col carattere separatore.
    Bye!
    scossa
    scossa's web site
    ___
    Se tu hai una mela, e io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee. (George Bernard Shaw)

  6. #6
    L'avatar di dracoscrigno
    Clicca e Apri
    Data Registrazione
    May 2016
    Località
    ferrara
    Età
    41
    Messaggi
    1741
    Versione Office
    office pro 2010
    Likes ricevuti
    374
    Likes dati
    206

    Re: Espressioni regolari RegexOptions.SingleLine

    secondo me scossa, ti sei perso questo intervento

    comunque ho fatto un passo avanti con l' espressione in linea anche se ancora non è perfetta perchè non riesco a farle marcare la string dal singolo carattere

    ([^*])(.{0,}\n{0,}){0,}([^*])



    Excel 2010 32 bit
    C
    D
    E
    F
    1
    TLIM (ricorsione di if then else) TLIM_2 (uso delle regex)
    Lunghezza
    TLIM
    Lunghezza
    TLIM 2
    2
    0
    0
    3
    Tre*spazi*a*DX Tre*spazi*a*DX
    14
    14
    4
    uno*spazio**a*SX uno*spazio**a*SX
    16
    16
    5
    uno*spazio*di*qua*e*di*la uno*spazio*di*qua*e*di*la
    25
    25
    6
    più*spazi*di*qua*e*di*la più*spazi*di*qua*e*di*la
    24
    24
    7
    0
    0
    8
    0
    0
    9
    Frase*con*ritorni*a*capo***
    ***ritorno*a*capo*1***
    ***ritorno*a*capo*2***
    ***ritorno*a*capo*3
    Frase*con*ritorni*a*capo***
    ***ritorno*a*capo*1***
    ***ritorno*a*capo*2***
    ***ritorno*a*capo*3
    93
    93
    10
    una*frase






    Con*tanti****A*capo
    una*frase






    Con*tanti****A*capo
    32
    32
    11
    w
    1
    0
    12
    ww ww
    2
    2
    Sheet: Foglio1




    la macro è un pò cambiata per far si che potessi fare a meno di passare sempre all IDE VBA ma potessi inserire il pattern sul foglio di calcolo

    Codice: 
    Function Tlim_2(ByVal sString As String, Optional sSep As String = " ", Optional sPattern As String = "([^\s])(.{0,}\n{0,}){0,}([^\s])") As String
    
    
     'by Draco
        Dim Elemento As Variant
        Dim EspressioneRegolare As Object
        Set EspressioneRegolare = CreateObject("VBScript.RegExp")
            
        With EspressioneRegolare
            .Global = True
            .MultiLine = False
            .Pattern = sPattern '"([^" & sSep & "])(.{0,}\n{0,}){0,}([^" & sSep & "])"      '  ([^*])(.{0,}\n{0,}){0,}([^*])
            If .test(sString) Then
                Tlim_2 = .Execute(sString).Item(0)
            End If
        End With
        Set EspressioneRegolare = Nothing
    End Function

    Inutile dire che, a me delle pippe sui millisecondi di processore non me ne può fregar di meno, se la risposta alla domanda è:
    NOn si può fare in VBA, Allora deve essere l' espressione regolare a risolvere il problema.
    Ne un replace, ne un ciclo.

    Il risultato deve essere un solo match e magari corretto ;)

    GRazie mille della comprensione

  7. #7

    L'avatar di scossa
    Clicca e Apri
    Data Registrazione
    Jul 2015
    Località
    Verona Provincia
    Età
    57
    Messaggi
    980
    Versione Office
    .
    Likes ricevuti
    322
    Likes dati
    0

    Re: Espressioni regolari RegexOptions.SingleLine

    Citazione Originariamente Scritto da dracoscrigno Visualizza Messaggio
    secondo me scossa, ti sei perso questo intervento
    Ops, vero ...

    Citazione Originariamente Scritto da dracoscrigno
    comunque ho fatto un passo avanti con l' espressione in linea anche se ancora non è perfetta perchè non riesco a farle marcare la string dal singolo carattere

    ([^*])(.{0,}\n{0,}){0,}([^*])


    Il risultato deve essere un solo match e magari corretto ;)
    [^*](.{0,}\n{0,}.{0,}[^*])*

    sta a te costruirla col separatore.
    Bye!
    scossa
    scossa's web site
    ___
    Se tu hai una mela, e io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee. (George Bernard Shaw)

  8. I seguenti utenti hanno dato un "Like"


  9. #8
    L'avatar di dracoscrigno
    Clicca e Apri
    Data Registrazione
    May 2016
    Località
    ferrara
    Età
    41
    Messaggi
    1741
    Versione Office
    office pro 2010
    Likes ricevuti
    374
    Likes dati
    206

    Re: Espressioni regolari RegexOptions.SingleLine

    Citazione Originariamente Scritto da scossa Visualizza Messaggio



    [^*](.{0,}\n{0,}.{0,}[^*])*

    sta a te costruirla col separatore.
    Scossa. perdonami ma non riesco a capirne la differenza


    Perchè questa:
    [^*](.{0,}\n{0,}.{0,})*[^*]

    non marca "***a" ma marca "***ab" mentre la tua invece, riesce marcare anche il singolo carattere?

    Poi, ho una domanda anche sulle parentesi tonde. io le uso anche per aiutarmi ad individuare visivamente gli elementi nell' espressione e vedendo che tu me li togli mi sorge spontanea la domanda:

    scrivere ([^*])(.{0,}\n{0,}){0,}([^*]) è uguale a scrivere[^*](.{0,}\n{0,}){0,}[^*] ?od anche, prendendo al tua come esempio:
    scrivere([^*])(.{0,}\n{0,}.{0,}[^*])* è uguale a scrivere [^*](.{0,}\n{0,}.{0,})*[^*] ?

  10. #9

    L'avatar di scossa
    Clicca e Apri
    Data Registrazione
    Jul 2015
    Località
    Verona Provincia
    Età
    57
    Messaggi
    980
    Versione Office
    .
    Likes ricevuti
    322
    Likes dati
    0

    Re: Espressioni regolari RegexOptions.SingleLine

    Ciao draco,

    innanzitutto bisogna tenere presente che la libreria delle Reg-Ex implementata in VBA è una versione semplificata rispetto alle funzionalità disponibili in altri linguaggi (Perl, Javascript ....) .
    Questo per spiegare perché certi Pattern testati nei motori on-line potrebbero non funzionare o dare risultati inattesi se usati in VBA.

    Ciò premesso, il tuo pattern [^*](.{0,}\n{0,}.{0,})*[^*] fa il match con una stringa che abbia
    Codice: 
    1 carattere qualsiasi che non sia *
    seguito da 0 o più (
    	0 o più caratteri qualsiasi
    	seguito da
    	0 o più LF
    	seguito da
    	0 o più caratteri qualsiasi
    )
    seguito da 
    1 carattere qualsiasi che non sia *
    quindi per avere un match la stringa deve avere almeno 2 caratteri che non siano *

    il mio pattern [^*](.{0,}\n{0,}.{0,}[^*])* invece fa il match con una stringa che abbia
    Codice: 
    1 carattere qualsiasi che non sia *
    seguito da 0 o più (
    	0 o più caratteri qualsiasi
    	seguito da
    	0 o più LF
    	seguito da
    	0 o più caratteri qualsiasi
    	seguito da 
    	1 carattere qualsiasi che non sia *
    )
    quindi per avere un match la stringa basta che abbia un carattere che non sia *

    Riguardo le parentesi non servono per "individuare visivamente gli elementi" ma per identificare i "gruppi di cattura", cioè quali blocchi del match catturare (e per assegnare un quantificatore all'intero gruppo).

    Ovviamente col codice dell'esempio il capturing group viene sfruttato solo per assegnare il quantificatore visto che restituire il match.
    Col mio pattern
    [^*](.{0,}\n{0,}.{0,}[^*])*
    del match dettagliato sopra verrebbe "trattenuta" solo la parte tra parentesi (p.e.: stringa: *ab*cd* -> match: ab*cd -> capturing group: b*cd)

    Per concludere, poiché la potenza delle Reg-Ex si esprime al meglio sfruttando proprio i capturing-group, questo sarebbe il (uno dei?) pattern per "catturare" la stringa "Tlimmata":

    ^\**(([^\*]*[\*\n]*[^\*]+)+)\**

    lascio a te il piacere di interpretarlo :-)

    Ovviamente il codice va leggermente modificato:
    Codice: 
    Function Tlim_2(ByVal sString As String, Optional sSep As String = " ") As String
     'by Draco
     '2016-09-27
     'rev scossa
     '2016-10-02
     
        Dim EspressioneRegolare As Object
        Dim oMatches As Object
        Dim sPattern As String
        
        If InStr("\^*+-|&.,;:_$", sSep) > 0 Then sSep = "\" & sSep 'escaped dei caratteri speciali
        sPattern = "^" & sSep & "*(([^" & sSep & "]*[" & sSep & "\n]*[^" & sSep & "]+)+)" & sSep & "*" '"^\**(([^\*]*[\*\n]*[^\*]+)+)\**"
        Set EspressioneRegolare = CreateObject("VBScript.RegExp")
        With EspressioneRegolare
            .Global = True
            .Pattern = sPattern
            If .test(sString) Then
              Set oMatches = .Execute(sString)
              Tlim_2 = oMatches(0).submatches(0)
            End If
        End With
        Set EspressioneRegolare = Nothing
        Set oMatches = Nothing
    End Function
    Bye!
    scossa
    scossa's web site
    ___
    Se tu hai una mela, e io ho una mela, e ce le scambiamo, allora tu ed io abbiamo sempre una mela per uno. Ma se tu hai un'idea, ed io ho un'idea, e ce le scambiamo, allora abbiamo entrambi due idee. (George Bernard Shaw)

Discussioni Simili

  1. Copiare formule in righe ad invervalli regolari
    Di And75 nel forum Domande su Excel in generale
    Risposte: 19
    Ultimo Messaggio: 12/09/16, 07:48
  2. Estrarre Testo da Stringhe non regolari e matching
    Di tmac720 nel forum Domande su Excel in generale
    Risposte: 9
    Ultimo Messaggio: 10/02/16, 16:44

Permessi di Scrittura

  • Tu non puoi inviare nuove discussioni
  • Tu non puoi inviare risposte
  • Tu non puoi inviare allegati
  • Tu non puoi modificare i tuoi messaggi
  •