Jump to content

Regexp headaches... Again (Solved)


benners
 Share

Recommended Posts

I wrote a function a while ago and it seems although it worked for that instance, it was never really bulletproof.

The idea was to check for word(s) in a string and return 1 or 0 or an array of matches. Basically all I wanted was to check command line parameters were specified correctly.

If my test string was '/forcerestart' and the search was forcerestart, as there was no '/' then it wouldn't be a match. Same as if the search was /forcerestar. I don't think the pattern can differentiate between as technically the string is in the test string.

Despite hours twiddling I end up here for help. I think it could be related to the pattern and '/' in the search string.

#Region #### Global Constants ########################
Global Const _
        $SFW_SEARCHANYWORDS = 0, _
        $SFW_SEARCHALLWORDS = 1, _
        $SFW_CASESENSITIVE = True, _
        $SFW_CASEINSENSITIVE = False
#EndRegion #### Global Constants ########################

#Region #### Includes ################################
#include <array.au3>
#include <StringConstants.au3>
#EndRegion #### Includes ################################

; this works with $SFW_SEARCHANYWORDS and $SFW_SEARCHALLWORDS
;~ Local $s_Test = 'WWW.google.com'
;~ Local $s_Search = '.com|google|www'

; this only works with $SFW_SEARCHANYWORDS. Is the '/' the problem??
Local $s_Test = '/unattended /silent /noerrors'
Local $s_Search = '/unattended|/silent|/noerrors'
;~ Local $v_Ret = _String_SearchForWords($s_Test, $s_Search, $SFW_SEARCHALLWORDS, $SFW_CASEINSENSITIVE, $STR_REGEXPARRAYGLOBALMATCH) ; errors
Local $v_Ret = _String_SearchForWords($s_Test, $s_Search, $SFW_SEARCHANYWORDS, $SFW_CASEINSENSITIVE, $STR_REGEXPARRAYGLOBALMATCH) ; works

If @error Then
    MsgBox(0, 'Error Occured', 'error : ' & @error & @CRLF & 'extended: ' & @extended & @CRLF & 'Return : ' & $v_Ret)
Else
    If IsArray($v_Ret) Then
        _ArrayDisplay($v_Ret)
    Else
        MsgBox(0, 'Positive Match', $v_Ret)
    EndIf
EndIf

; #FUNCTION# ====================================================================================================================
; Name ..........: _String_SearchForWords
; Description ...: Check a string for the existance of a word or words
; Syntax ........: _String_SearchForWords($s_Test, $s_Search[, $i_AllWords = 0[, $b_Case = False[, $i_Return = 0]]])
; Parameters ....: $s_Test     - A string value. The string to check for the words
;                  $s_Search   - A string value. The regular expression to match
;                  $i_AllWords - [optional] An integer value. Default is $SFW_SEARCHANYWORDS
;                                  $SFW_SEARCHANYWORDS - Any words can be found
;                                  $SFW_SEARCHALLWORDS - All the words must be found
;                  $b_Case     - [optional] A boolean value. Default is $SFW_CASEINSENSITIVE
;                                  $SFW_CASESENSITIVE   - search matching case sense
;                                  $SFW_CASEINSENSITIVE - search case insensitive
;                  $i_Return   - [optional] An integer value. Default is $STR_REGEXPMATCH
;                                  $STR_REGEXPMATCH                 - Returns 1 (match) or 0 (no match)
;                                  $STR_REGEXPARRAYMATCH            - Return array of matches.
;                                  $STR_REGEXPARRAYFULLMATCH        - Return array of matches including the full match
;                                  $STR_REGEXPARRAYGLOBALMATCH      - Return array of global matches
;                                  $STR_REGEXPARRAYGLOBALFULLMATCH  - Return an array of arrays containing global matches
;                                                                     including the full match
; Return values .: Success - Returns either true\false or an array of matches, depending on $i_Return value
;                  Failure - Sets @error to non zero
;                          - Sets @extended to non zero
;                          - Returns a string value with the error reason
; Author ........: Benners
; Modified ......: yep, wears contact lenses
; Remarks .......: Thanks to jguinch for the help
; Related .......: no we're not
; Link ..........: https://www.autoitscript.com/forum/topic/180056-stringregexp-headscratching/
; ===============================================================================================================================
Func _String_SearchForWords($s_Test, $s_Search, $i_AllWords = $SFW_SEARCHANYWORDS, $b_Case = $SFW_CASEINSENSITIVE, $i_Return = $STR_REGEXPMATCH)
    ; decide if case sensitive searching
    Local $s_Case = $b_Case ? "(?s)" : "(?is)"

    ; search for any of the words and any matches
    Local $s_Pattern = '(' & $s_Search & ')'

    ; change the pattern to search for all the words and give an exact match
    If $i_AllWords Then $s_Pattern = "^" & StringRegExpReplace($s_Search, "([^|]+)(?:\||$)", "(?=.*\\b(\\Q$1\\E)\\b)")

    Local $v_Ret = StringRegExp($s_Test, $s_Case & $s_Pattern, $i_Return)

    If @error Then
        Local $s_Return = ''

        Switch $i_Return
            Case 0
                $s_Return = 'Bad pattern. @extended = offset of error in pattern'
            Case 1, 2
                Switch @error
                    Case 0
                        $s_Return = 'Array is valid. Check @extended for next offset'
                    Case 1
                        $s_Return = 'Array is invalid. No matches.'
                    Case 2
                        $s_Return = 'Bad pattern, array is invalid. @extended = offset of error in pattern.'
                EndSwitch
            Case 3, 4
                Switch @error
                    Case 0
                        $s_Return = 'Array is valid'
                    Case 1
                        $s_Return = 'Array is invalid. No matches.'
                    Case 2
                        $s_Return = 'Bad pattern, array is invalid. @extended = offset of error in pattern.'
                EndSwitch
        EndSwitch

        Return SetError(@error, @extended, $s_Return)
    EndIf

    Return $v_Ret
EndFunc   ;==>_String_SearchForWords

 

Link to comment
Share on other sites

18 hours ago, benners said:

Basically all I wanted was to check command line parameters were specified correctly.
(...)
If my test string was '/forcerestart' and the search was forcerestart, as there was no '/' then it wouldn't be a match. Same as if the search was /forcerestar. I don't think the pattern can differentiate between as technically the string is in the test string.

I don't understand the way you go
Normally the regex should check if everything is correct in the test string, so the pattern should mention the correct command line parameters

#Include <Array.au3>

Local $s_Test = '/unattende silent /noerrors'
Local $s_Search = '/unattended|/silent|/noerrors'

$s_Pattern = '(?|' & $s_Search & ')(?=\b|$)'

$a_Ret = StringRegExp($s_Test, $s_Pattern, 3)
_ArrayDisplay($a_Ret)

$v_Ret = StringRegExp($s_Test, $s_Pattern, 0)
Msgbox(0,"", $v_Ret = 1 ? UBound($a_Ret) & " are ok " : "error")

 

Link to comment
Share on other sites

@Bert Cheers. I normally use regex101 and look through the au3 files for regexp examples.

@mikell "I don't understand the way you go", You and me both :) I think I got some of the regex from _stringbetween. It's been that long , I have forgotten exactly and I'm sh1te with regexp. Your solution works so I'm going to have a play.

Thanks both for the replies

Link to comment
Share on other sites

  • benners changed the title to Regexp headaches... Again (Solved)

Well I thought my search was over. Some of the command line arguments contain asterisks which I know is a special character in  regex. So again all I need is to check the specified parameter conforms exaclty to one string in $s_Search

I have tried to escape the * using a \ and also tried using \Q and \E to quote them literally but nothing got me the result I need.

I ended up using the code below, but for learning and curiosity, can it be done using regex?

Local $s_Test = '/L*'
Local $s_Search = '/L*|/L*v|/L*x|/L*xv'

If _ArraySearch(StringSplit($s_Search, '|'), $s_test, 0, 0, 0, 2) <> -1 Then MsgBox(0, '', 'switch found')

 

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...