Jump to content

Recommended Posts

Posted (edited)

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

Share this post


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

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

You shouldn't care about \e

\e  Represents the "escape" control character (Chr(27)).

BTW If you don't need case sensitivity, this (using lowercase) could work

$s = "C:\Test\Example\"
$r = StringRegExpReplace($s, '(?i)\Qc:\test\example\\E', "***")
Msgbox(0,"", $r)

 

Share this post


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...