Jump to content

Recommended Posts

Hey RegEx Experts, quick question here...

I'm searching for text using RegEx and I need to quote things exactly. Normally, I wrap the text in \Q and \E and this works great. I was parsing some paths today, however, and I realized that this is broken with a Folder/File that starts with E... like this:

Main()

Func Main()

    Local $sConfig = @ScriptDir & "\config.ini"

    Local $sPath1 = "C:\Test\Example\"
    Local $sPath2 = "C:\Test\Test\"

    IniWrite($sConfig, $sPath1, "Test", "Test")
    IniWrite($sConfig, $sPath2, "Test2", "Test2")

    Local $sText = FileRead($sConfig)
    ConsoleWrite($sPath1 & " -- " & __IniEx_SectionText($sText, $sPath1) & @CRLF& @CRLF)
    ConsoleWrite($sPath2 & " -- " & __IniEx_SectionText($sText, $sPath2) & @CRLF)

EndFunc

Func __IniEx_SectionText($sText, $sSection)

    Local $sRegEx = __RegEx_EscapedQuoted("(?m)^\[", $sSection, "\]$\s+((?:.*=.*\r?\n)*)")
    ConsoleWrite("RegEx: " & $sRegEx & @CRLF)
    Local $aResult = StringRegExp($sText, $sRegEx, 3)
    If @error Then Return SetError(1, @error, False)

    Return $aResult[0]

EndFunc

Func __RegEx_EscapedQuoted($sRegExLeading, $sSearch, $sRegExEnding)

    Return $sRegExLeading & "\Q" & $sSearch & "\E" & $sRegExEnding

EndFunc

Func __RegEx_EscapedQuoted2($sRegExLeading, $sSearch, $sRegExEnding)

    $sSearch = StringReplace($sSearch, "\E", "\E\\E\Q")

    Return $sRegExLeading & "\Q" & $sSearch & "\E" & $sRegExEnding

EndFunc

The C:\Test\Example\ path will fail to return because it contains the \E, while C:\Test\Test\ returns as expected

Is there another way to quote things like this in RegEx? How can I fix __RegEx_EscapedQuoted to make this work?

Edit: I need a rubber duck. I explained the problem as simply as possible and then solved it... although it is ugly. Replacing \E with \E\\E\Q works :D Any better solutions than my second attempt?

Edited by seadoggie01

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts

Link to post
Share on other sites

Late last year I came across the same problem. These are the two methods I found that worked.

#include <Array.au3>

Local $Paths = 'C:\Users\' & @CRLF & _
        'C:\EEC (1)\someother file' & @CRLF & _
        'C:\MSfree\' & @CRLF & _
        'C:\EEC (1)\'
Local $sSearch = "C:\EEC"

; --------------------- Method 1 ----------------------------------
; Check if "\E" is in $sSearch.  If "\E" is present, replace "\E" with "\E\\E\Q",  because of the "\Q" & $sSearch & "\E" in RE pattern.
Local $sSearchA = (StringInStr($sSearch, "\E") ? StringReplace($sSearch, "\E", "\E\\E\Q") : $sSearch)
;ConsoleWrite("\Q" & $sSearchA & "\E" & @CRLF)
Local $a = StringRegExp($Paths, "(\Q" & $sSearchA & "\E.*)", 3)
_ArraySort($a)
;_ArrayDisplay($a)
If UBound($a) > 1 Then
    For $i = 1 To UBound($a) - 1 ; Keep $a1[0]
        $sSearchB = (StringInStr($a[$i], "\E") ? StringReplace($a[$i], "\E", "\E\\E\Q") : $a[$i])
        ConsoleWrite("\Q" & $sSearchB & "\E" & @CRLF)
        Local $sOutput = StringRegExpReplace($Paths, "(\Q" & $sSearchB & "\E\R?)", "")
    Next
Else
    Local $sOutput = StringRegExpReplace($Paths, "(\Q" & $sSearchA & "\E.*\R?)", "")
EndIf
MsgBox(0, "\Q...\E", $sOutput)

; Or

; --------------------- Method 2 ----------------------------------
; Beware "(1)", where (n) tests whether the capturing group with absolute number n matched.
$sSearch = StringRegExpReplace($sSearch, "([\\()\.^$|\[\]{}*+?#])", "\\$1")
;ConsoleWrite($sSearch & @CRLF)

Local $a1 = StringRegExp($Paths, "(" & $sSearch & ".*)", 3)
_ArraySort($a1)
;_ArrayDisplay($a1)
If UBound($a1) > 1 Then
    For $i = 1 To UBound($a1) - 1 ; Keep $a1[0]
        $sSearchC = StringRegExpReplace($a1[$i], "([\\()\.^$|\[\]{}*+?#])", "\\$1")
        ConsoleWrite($sSearchC & @CRLF)
        Local $sOutput = StringRegExpReplace($Paths, "(" & $sSearchC & "\R?)", "")
    Next
Else
    Local $sOutput = StringRegExpReplace($Paths, "(" & $sSearch & ".*\R?)", "")
EndIf
MsgBox(0, "\\,(,)", $sOutput)

#cs ; Both methods return:-
C:\Users\
C:\MSfree\
C:\EEC (1)\
#ce

 

Link to post
Share on other sites
  • 2 weeks later...

Thought I should update this because I was testing things with case sensitivity, so my previous function failed to match. I've updated it to this:

Func __RegEx_EscapedQuoted2($sRegExLeading, $sSearch, $sRegExEnding)

    $sSearch = StringReplace($sSearch, "\E", "\E\\E\Q", 0, 1)
    $sSearch = StringReplace($sSearch, "\e", "\E\\e\Q", 0, 1)

    Return $sRegExLeading & "\Q" & $sSearch & "\E" & $sRegExEnding

EndFunc

StringReplace isn't case sensitive by default, so this replaces both \E and \e with case sensitivity.

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...