Sign in to follow this  
Followers 0
JohnOne

Looking for a function

18 posts in this topic

#1 ·  Posted (edited)

I find myself needing a function similar to _StringBetween but also to return the positions of any strings found.

I've searched for this without any luck, but before I start to write one, just wondering if anyone has seen such a function around the forum?

Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

So far I have my _StringsInStr func It will be mutilated to _StringBetweenEx soon, so I'll put it here for posterity.

#cs
    $Array = _StringsInStr("The mad mad mad mad the mad cat on mad day in mad dog ate mad mad mad the mad cat on mad day in mad land", "mad")
    If Not IsArray($Array) Then
    Exit MsgBox(0, 0, 0)
    EndIf

_ArrayDisplay($Array)
#ce

Func _StringsInStr($SearchIn, $SearchFor)
    Local $Size = 10
    Local $aPos[$Size], $Found = 0, $Index = 0

    Do
        $Found = StringInStr($SearchIn, $SearchFor, 0, 1, $Found + 1)
        If $Found Then
            If $Index = $Size Then
                $Size += $Size
                ReDim $aPos[$Size]
            EndIf
            $aPos[$Index] = $Found
            $Index += 1

        EndIf
    Until $Found = 0 Or @error

    If $Index = 0 Then
        Return SetError(1, 0, 0)
    EndIf

    ReDim $aPos[$Index]

    Return $aPos

EndFunc   ;==>_StringsInStr
Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

... string between and position where found

this old listing has a bug (that is: if a string inside delimiters is also outside of delimiters it returns a wrong position)

#include <Array.au3>
#include <String.au3>
Example()

Func Example()
    $sMyString = "[18]zero[20]hello[18]example[5]one[500]two[60]"
    $aResult = _StringBetweenAndPos($sMyString)
    _ArrayDisplay($aResult)
EndFunc   ;==>Example
;
Func _StringBetweenAndPos($sMyString)
    Local $aArray = _StringBetween($sMyString, "[", "]")
    If @error Then Return SetError(1, 0, "")
    Local $aResult[UBound($aArray)][2], $iStart = 1
    For $i = 0 To UBound($aArray) - 1
        $aResult[$i][0] = $aArray[$i]
        $aResult[$i][1] = StringInStr($sMyString, $aResult[$i][0], 0, 1, $iStart)
        $iStart = $aResult[$i][1] + 1
    Next
    Return $aResult
EndFunc   ;==>_StringBetweenAndPos

#include <Array.au3>
#include <String.au3>
Example()

Func Example()
    $sMyString = "[18]zero[20]hello18[18]example[5]one[500]two[60]"
    $aResult = _StringBetweenAndPos($sMyString, "[", "]")
    _ArrayDisplay($aResult)
EndFunc   ;==>Example

Func _StringBetweenAndPos($sMyString, $sDelim1, $sDelim2)
    Local $aArray = _StringBetween($sMyString, $sDelim1, $sDelim2)
    If @error Then Return SetError(1, 0, "")
    Local $aResult[UBound($aArray)][2], $iStart = 1
    For $i = 0 To UBound($aArray) - 1
        $aResult[$i][0] = $aArray[$i]
        $aResult[$i][1] = StringInStr($sMyString, $sDelim1 & $aResult[$i][0] & $sDelim2, 0, 1, $iStart) + 1
        $iStart = $aResult[$i][1]
    Next
    Return $aResult
EndFunc   ;==>_StringBetweenAndPos

edit

new listing debugged

Edited by Chimp
1 person likes this

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

 

So far I have my _StringsInStr func It will be mutilated to _StringBetweenEx soon, so I'll put it here for posterity.

#cs
    $Array = _StringsInStr("The mad mad mad mad the mad cat on mad day in mad dog ate mad mad mad the mad cat on mad day in mad land", "mad")
    If Not IsArray($Array) Then
    Exit MsgBox(0, 0, 0)
    EndIf

_ArrayDisplay($Array)
#ce

Func _StringsInStr($SearchIn, $SearchFor)
    Local $Size = 10
    Local $aPos[$Size], $Found = 0, $Index = 0

    Do
        $Found = StringInStr($SearchIn, $SearchFor, 0, 1, $Found + 1)
        If $Found Then
            If $Index = $Size Then
                $Size += $Size
                ReDim $aPos[$Size]
            EndIf
            $aPos[$Index] = $Found
            $Index += 1

        EndIf
    Until $Found = 0 Or @error

    If $Index = 0 Then
        Return SetError(1, 0, 0)
    EndIf

    ReDim $aPos[$Index]

    Return $aPos

EndFunc   ;==>_StringsInStr

 

your function a bit semplified .... by using StringReplace($SearchIn, $SearchFor, $SearchFor) and then reading @extended, you know the  nr. of occurrences of searched string...

#include <Array.au3>

$Array = _StringsInStr("The mad mad mad mad the mad cat on mad day in mad dog ate mad mad mad the mad cat on mad day in mad land", "mad")
If Not IsArray($Array) Then
    Exit MsgBox(0, 0, 0)
EndIf

_ArrayDisplay($Array)

Func _StringsInStr($SearchIn, $SearchFor)
    StringReplace($SearchIn, $SearchFor, $SearchFor)
    $iOccurrences = @extended
    If Not $iOccurrences Then Return SetError(1, 0, "")
    Local $aPos[$iOccurrences]
    For $i = 1 To $iOccurrences
        $aPos[$i - 1] = StringInStr($SearchIn, $SearchFor, 0, $i)
    Next
    Return $aPos
EndFunc   ;==>_StringsInStr
1 person likes this

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

maybe its semplified but yout preformance isnt good, another way around

 

#include <Array.au3>
$loops = 1000
$str = "The mad mad mad mad the mad cat on mad day in mad dog ate mad mad mad the mad cat on mad day in mad landThe mad mad mad mad the mad cat on mad day in mad dog ate mad mad mad the mad cat on mad day in mad landThe mad mad mad mad the mad cat on mad day in mad dog ate mad mad mad the mad cat on mad day in mad landThe mad mad mad mad the mad cat on mad day in mad dog ate mad mad mad the mad cat on mad day in mad land"

$in = TimerInit()
For $x = 1 To $loops
    $Array = _StringsInStr1($str, "mad");John
Next
$time = TimerDiff($in)
ConsoleWrite($time & " John" & @CRLF)
_ArrayDisplay($Array, $time)

$in = TimerInit()
For $x = 1 To $loops
    $Array = _StringsInStr2($str, "mad");bogQ
Next
$time = TimerDiff($in)
ConsoleWrite($time & " bogQ" & @CRLF)
_ArrayDisplay($Array, $time)

$in = TimerInit()
For $x = 1 To $loops
    $Array = _StringsInStr3($str, "mad");Chimp
Next
$time = TimerDiff($in)
ConsoleWrite($time & " Chimp" & @CRLF)
_ArrayDisplay($Array, $time)

Func _StringsInStr1($SearchIn, $SearchFor)
    Local $Size = 10
    Local $aPos[$Size], $Found = 0, $Index = 0
    Do
        $Found = StringInStr($SearchIn, $SearchFor, 0, 1, $Found + 1)
        If $Found Then
            If $Index = $Size Then
                $Size += $Size
                ReDim $aPos[$Size]
            EndIf
            $aPos[$Index] = $Found
            $Index += 1

        EndIf
    Until $Found = 0 Or @error

    If $Index = 0 Then
        Return SetError(1, 0, 0)
    EndIf

    ReDim $aPos[$Index]

    Return $aPos

EndFunc   ;==>_StringsInStr1

Func _StringsInStr2($SearchIn, $SearchFor)
    Local $aArray = StringSplit($SearchIn, $SearchFor, 1)
    If @error Then Return SetError(1, 0, 0)
    Local $sLen = StringLen($SearchFor)
    ReDim $aArray[$aArray[0]];remove last unneeded split
    $aArray[0] -= 1;Correct the number of returned values
    $aArray[1] = StringLen($aArray[1]) + 1;Calculate only first element with +1 coz other elements are calculated upon this element
    For $x = 2 To $aArray[0]
        $aArray[$x] = StringLen($aArray[$x]) + $aArray[$x - 1] + $sLen
    Next
    Return $aArray
EndFunc   ;==>_StringsInStr2

Func _StringsInStr3($SearchIn, $SearchFor)
    StringReplace($SearchIn, $SearchFor, $SearchFor)
    $iOccurrences = @extended
    If Not $iOccurrences Then Return SetError(1, 0, "")
    Local $aPos[$iOccurrences]
    For $i = 1 To $iOccurrences
        $aPos[$i - 1] = StringInStr($SearchIn, $SearchFor, 0, $i)
    Next
    Return $aPos
EndFunc   ;==>_StringsInStr3
edit: small count of ellements correction Edited by bogQ
1 person likes this

TCP server and client - Learning about TCP servers and clients connection
Au3 oIrrlicht - Irrlicht project
Au3impact - Another 3D DLL game engine for autoit. (3impact 3Drad related)



460px-Thief-4-temp-banner.jpg
There are those that believe that the perfect heist lies in the preparation.
Some say that it’s all in the timing, seizing the right opportunity. Others even say it’s the ability to leave no trace behind, be a ghost.

 

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

maybe its semplified but yout preformance isnt good, another way around

<snip>

 

a bit improved my performances... but still a liitle slower than your

#include <Array.au3>
$loops = 1000
$str = "The mad mad mad mad the mad cat on mad day in mad dog ate mad mad mad the mad cat on mad day in mad landThe mad mad mad mad the mad cat on mad day in mad dog ate mad mad mad the mad cat on mad day in mad landThe mad mad mad mad the mad cat on mad day in mad dog ate mad mad mad the mad cat on mad day in mad landThe mad mad mad mad the mad cat on mad day in mad dog ate mad mad mad the mad cat on mad day in mad land"

$in = TimerInit()
For $x = 1 To $loops
    $Array = _StringsInStr1($str, "mad");John
Next
$time = TimerDiff($in)
ConsoleWrite($time & " John" & @CRLF)
_ArrayDisplay($Array, $time)

$in = TimerInit()
For $x = 1 To $loops
    $Array = _StringsInStr2($str, "mad");bogQ
Next
$time = TimerDiff($in)
ConsoleWrite($time & " bogQ" & @CRLF)
_ArrayDisplay($Array, $time)

$in = TimerInit()
For $x = 1 To $loops
    $Array = _StringsInStr3($str, "mad");Chimp
Next
$time = TimerDiff($in)
ConsoleWrite($time & " Chimp" & @CRLF)
_ArrayDisplay($Array, $time)

Func _StringsInStr1($SearchIn, $SearchFor)
    Local $Size = 10
    Local $aPos[$Size], $Found = 0, $Index = 0
    Do
        $Found = StringInStr($SearchIn, $SearchFor, 0, 1, $Found + 1)
        If $Found Then
            If $Index = $Size Then
                $Size += $Size
                ReDim $aPos[$Size]
            EndIf
            $aPos[$Index] = $Found
            $Index += 1

        EndIf
    Until $Found = 0 Or @error

    If $Index = 0 Then
        Return SetError(1, 0, 0)
    EndIf

    ReDim $aPos[$Index]

    Return $aPos

EndFunc   ;==>_StringsInStr1

Func _StringsInStr2($SearchIn, $SearchFor)
    Local $aArray = StringSplit($SearchIn, $SearchFor, 1)
    If @error Then Return SetError(1, 0, 0)
    Local $sLen = StringLen($SearchFor)
    ReDim $aArray[$aArray[0]];remove last unneeded split
    $aArray[0] -= 1;Correct the number of returned values
    $aArray[1] = StringLen($aArray[1]) + 1;Calculate only first element with +1 coz other elements are calculated upon this element
    For $x = 2 To $aArray[0]
        $aArray[$x] = StringLen($aArray[$x]) + $aArray[$x - 1] + $sLen
    Next
    Return $aArray
EndFunc   ;==>_StringsInStr2

Func _StringsInStr3($SearchIn, $SearchFor)
    StringReplace($SearchIn, $SearchFor, $SearchFor)
    $iOccurrences = @extended
    If Not $iOccurrences Then Return SetError(1, 0, "")
    Local $iSearchLen = StringLen($SearchFor), $aPos[$iOccurrences + 1] = [1 - $iSearchLen]
    For $i = 1 To $iOccurrences
        $aPos[$i] = StringInStr($SearchIn, $SearchFor, 2, 1, $aPos[$i - 1] + $iSearchLen)
    Next
    $aPos[0] = $iOccurrences
    Return $aPos
EndFunc   ;==>_StringsInStr3

edit:

little debug

Edited by Chimp
1 person likes this

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

Well, no, I just found it with the post button unpressed on my other computer, duh!

Here's what I came up with.

#cs
$Array = _StringBetweenEX("[my]zero[strings]hello[to]example[find]one[in]two[brackets]", "[", "]")
If Not IsArray($Array) Then
    Exit MsgBox(0, 0, 0)
EndIf

_ArrayDisplay($Array)
#ce

Func _StringBetweenEX($SearchIn, $sStart, $sEnd)
    Local $Size = 10
    Local $aPos[$Size][3], $Found = 0, $Found2 = 0, $Index = 0

    Do
        $Found = StringInStr($SearchIn, $sStart, 0, 1, $Found + 1)
        If $Found Then
            $Found2 = StringInStr($SearchIn, $sEnd, 0, 1, $Found + 1)
        EndIf
        If $Found And $Found2 Then
            If $Index = $Size Then
                $Size += $Size
                ReDim $aPos[$Size][3]
            EndIf
            $aPos[$Index][0] = StringMid($SearchIn, $Found + 1, $Found2 - ($Found + 1))
            $aPos[$Index][1] = $Found
            $aPos[$Index][2] = $Found2

            $Index += 1
        EndIf
    Until $Found = 0 Or @error

    If $Index = 0 Then
        Return SetError(1, 0, 0)
    EndIf

    ReDim $aPos[$Index][3]

    Return $aPos

EndFunc   ;==>_StringBetweenEX

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

Hmmz, if only this could be done somewhat reliably with occurances of capture groups in regex matches over a string instead of substrings between fixed delimiters...

#include <Array.au3>

;                               0         0         0         0         0
;                      123456789 123456789 123456789 123456789 123456789
$stringy =            "I 1want to2 (this --> w <-- should not be counted," ;   1-50
$stringy = $stringy & " this --> 1 w 1 <-- should) know 3things4 about al" ;  51-100
$stringy = $stringy & "l 5strings67 beween digits8. This --> 12 <-- shoul" ; 101-150
$stringy = $stringy & "d lead to an empty string which cannot be indicate" ; 151-200
$stringy = $stringy & "d by a string position (it should lead to 0,0). 9 " ; 201-250
$stringy = $stringy & "This sentence should show up.10 This shouldn't...." ; 251-300

_ArrayDisplay(_stringRegExpWithPositions($stringy, "[0-9](.*?)[0-9]"))

Exit

Func _stringRegExpWithPositions($searchIn, $regex)
        ; remember the initial regex array and the count of found items; we'll need that later. If nothing found, just return False.
    $aFound = StringRegExp($searchIn, $regex, 3)
    $aFoundCount = UBound($aFound)
    If @error Then Return False

    Dim $result[0][3]
        ; We're going to work through the $searchIn, hunting the strings that matched the regex to find out their positions.
    $iIndex = 0

    For $i In $aFound
        If $i == "" Then
            ; Can't indicate the position of an empty string in a string, since all positions in a string have a non-empty char.
            ; Add the element ("") to the array with positions 0,0
            Local $newItem[1][3] = [["", 0, 0]]
        Else
            ; Ok, we got something of which we can find the position.
            Do
                ; We need to make sure that the regex-match that we found doesn't happen to occur earlier in the string too
                ; For instance, "x1x1" has one match for "[0-9](.*?)[0-9]". The captured group we want is on pos 3, but "x" is found at pos 1 too.
                ; To be safe, we compare whether the regex match actually changes when we cut out the current occurance of the substring.
                $iIndex = StringInStr($searchIn, $i, 0, 1, $iIndex + 1)
                $iLength = StringLen($i)
                $testString = StringLeft($searchIn, $iIndex - 1) & StringMid($searchIn, $iIndex + $iLength)
            Until Not _isArrayEqual(StringRegExp($searchIn, $regex, 3), StringRegExp($testString, $regex, 3))
            ; Add the found substring and the starting and ending positions to our result array.
            Local $newItem[1][3] = [[$i, $iIndex, $iIndex + StringLen($i) - 1]]
            ; Local $newItem[1][3] = [[$i, $iIndex, StringLen($i)]] or, more insteresting to me personally, starting position and length...
        EndIf
        _ArrayAdd($result, $newItem)
    Next

    Return $result
EndFunc   ;==>_stringRegExpWithPositions

Func _isArrayEqual($a1, $a2)
    ; compares only 1d arrays of the same size
    If Not IsArray($a1) Or Not IsArray($a2) Or UBound($a1) <> UBound($a2) Or UBound($a1, 2) <> 0 Then Return False

    For $i = 0 To UBound($a1) - 1
        If $a1[$i] <> $a2[$i] Then Return False
    Next

    Return True
EndFunc   ;==>_isArrayEqual

Pretty nifty if I do say so myself :) Turns out it even works pretty well for nested capture groups (like "[0-9]((.*?) .*?)[0-9]").

 

1 person likes this

Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

Here my idea:

#include <Array.au3>

;         1234567890123456789012345678901234567890123456789012345678901234567890
$sText = "[#my#]zero[#strings#]hello[#to#]example[#find#]one[#in#]two[#brackets#]"

$aResult = _StringGetPosEx($sText, "[#", "#]")
_ArrayDisplay($aResult)

Func _StringGetPosEx($sString, $sStart, $sEnd, $bCase = False)
    StringReplace($sString, $sStart, $sStart)
    Local $iStarts = @extended
    StringReplace($sString, $sEnd, $sEnd)
    Local $iEnds = @extended, $iLenL = StringLen($sStart), $iLenR = StringLen($sEnd)
    Local $aPosStarts[$iStarts], $aPosEnds[$iEnds], $i, $iMin
    $iMin = UBound($aPosStarts) < UBound($aPosEnds) ? UBound($aPosStarts) : UBound($aPosEnds)
    For $i = 0 To $iMin - 1
        $aPosStarts[$i] = StringInStr($sString, $sStart, $bCase, $i + 1, 1)
        $aPosEnds[$i] = StringInStr($sString, $sEnd, $bCase, $i + 1, 1)
    Next
    Local $aResult[$iMin][3]
    For $i = 0 To UBound($aResult) - 1
        $aResult[$i][0] = StringMid($sString, $aPosStarts[$i] + $iLenL, $aPosEnds[$i] - $aPosStarts[$i] - $iLenR)
        $aResult[$i][1] = $aPosStarts[$i] + $iLenL
        $aResult[$i][2] = $aPosEnds[$i] - 1
    Next
    Return $aResult
EndFunc

Works for this particular simple example with the brackets, might not for other constellations (not tested).

Br,

UEZ

Edited by UEZ
1 person likes this

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

I just don't know where do you find this brain teasers JohnOne...
my try to wrap my head around this one resulted in this, and i'm not even sure if its working correctly or how it preform, and is it even doing what it need to do, but it was a fun try and im off no sleep now...

#include <Array.au3>
$var = "aha [amy aa] zero [a strings a] hello [am to a] example[afinda]onea[aina]two[abracketsbracketa]afterbrackettt [aa]"
;~ $var = "[][my]zero[strings]hello[to]example[find]one[in]two[brackets]"
;~ $var = "aha [amy aa]"
;~ $var = ""

$Array = _PosFrombetween($var, '[a', 'a]')
;~ $Array = _PosFrombetween($var, '[', ']')
_ArrayDisplay($Array)

Func _PosFrombetween($var, $start, $end)
    Local $verb = "(.*?)(\Q" & $start & "\E)(.*?)(\Q" & $end & "\E)";edited from some udf
    Local $arr = StringRegExp($var, $verb, 3)
    If Not IsArray($arr) Then Return SetError(1, 0, 0)
    _ArrayDisplay($arr, 'words');comment out this line if needed, it's here only for testing purpose
    Local $Array[(UBound($arr) / 4)][4]
    For $x = 2 To UBound($arr) - 1 Step 4
        $Array[(($x + 2) / 4) - 1][0] = '"' & $arr[$x] & '"'
        Select
            Case $x <> 2
                $Array[(($x + 2) / 4) - 1][1] = StringLen($arr[$x - 3]) + StringLen($arr[$x - 2]) + StringLen($arr[$x - 1]) + $Array[((($x + 2) / 4) - 1) - 1][3]
            Case Else
                $Array[(($x + 2) / 4) - 1][1] = StringLen($arr[$x - 2]) + StringLen($arr[$x - 1])
        EndSelect
        $Array[(($x + 2) / 4) - 1][2] = StringLen($arr[$x])
        $Array[(($x + 2) / 4) - 1][3] = $Array[(($x + 2) / 4) - 1][1] + $Array[(($x + 2) / 4) - 1][2]
    Next
    Return $Array
EndFunc   ;==>_PosFrombetween
Edited by bogQ
1 person likes this

TCP server and client - Learning about TCP servers and clients connection
Au3 oIrrlicht - Irrlicht project
Au3impact - Another 3D DLL game engine for autoit. (3impact 3Drad related)



460px-Thief-4-temp-banner.jpg
There are those that believe that the perfect heist lies in the preparation.
Some say that it’s all in the timing, seizing the right opportunity. Others even say it’s the ability to leave no trace behind, be a ghost.

 

Share this post


Link to post
Share on other sites

 

Hmmz, if only this could be done somewhat reliably with occurances of capture groups in regex matches over a string instead of substrings between fixed delimiters...

#include <Array.au3>

;                               0         0         0         0         0
;                      123456789 123456789 123456789 123456789 123456789
$stringy =            "I 1want to2 (this --> w <-- should not be counted," ;   1-50
$stringy = $stringy & " this --> 1 w 1 <-- should) know 3things4 about al" ;  51-100
$stringy = $stringy & "l 5strings67 beween digits8. This --> 12 <-- shoul" ; 101-150
$stringy = $stringy & "d lead to an empty string which cannot be indicate" ; 151-200
$stringy = $stringy & "d by a string position (it should lead to 0,0). 9 " ; 201-250
$stringy = $stringy & "This sentence should show up.10 This shouldn't...." ; 251-300

_ArrayDisplay(_stringRegExpWithPositions($stringy, "[0-9](.*?)[0-9]"))

Exit

Func _stringRegExpWithPositions($searchIn, $regex)
        ; remember the initial regex array and the count of found items; we'll need that later. If nothing found, just return False.
    $aFound = StringRegExp($searchIn, $regex, 3)
    $aFoundCount = UBound($aFound)
    If @error Then Return False

    Dim $result[0][3]
        ; We're going to work through the $searchIn, hunting the strings that matched the regex to find out their positions.
    $iIndex = 0

    For $i In $aFound
        If $i == "" Then
            ; Can't indicate the position of an empty string in a string, since all positions in a string have a non-empty char.
            ; Add the element ("") to the array with positions 0,0
            Local $newItem[1][3] = [["", 0, 0]]
        Else
            ; Ok, we got something of which we can find the position.
            Do
                ; We need to make sure that the regex-match that we found doesn't happen to occur earlier in the string too
                ; For instance, "x1x1" has one match for "[0-9](.*?)[0-9]". The captured group we want is on pos 3, but "x" is found at pos 1 too.
                ; To be safe, we compare whether the regex match actually changes when we cut out the current occurance of the substring.
                $iIndex = StringInStr($searchIn, $i, 0, 1, $iIndex + 1)
                $iLength = StringLen($i)
                $testString = StringLeft($searchIn, $iIndex - 1) & StringMid($searchIn, $iIndex + $iLength)
            Until Not _isArrayEqual(StringRegExp($searchIn, $regex, 3), StringRegExp($testString, $regex, 3))
            ; Add the found substring and the starting and ending positions to our result array.
            Local $newItem[1][3] = [[$i, $iIndex, $iIndex + StringLen($i) - 1]]
            ; Local $newItem[1][3] = [[$i, $iIndex, StringLen($i)]] or, more insteresting to me personally, starting position and length...
        EndIf
        _ArrayAdd($result, $newItem)
    Next

    Return $result
EndFunc   ;==>_stringRegExpWithPositions

Func _isArrayEqual($a1, $a2)
    ; compares only 1d arrays of the same size
    If Not IsArray($a1) Or Not IsArray($a2) Or UBound($a1) <> UBound($a2) Or UBound($a1, 2) <> 0 Then Return False

    For $i = 0 To UBound($a1) - 1
        If $a1[$i] <> $a2[$i] Then Return False
    Next

    Return True
EndFunc   ;==>_isArrayEqual

Pretty nifty if I do say so myself :) Turns out it even works pretty well for nested capture groups (like "[0-9]((.*?) .*?)[0-9]").

 

That is beautiful.

It's a script and it's a book :)


AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

That is beautiful.

It's a script and it's a book :)

 

Thanks... And yes, my colleagues gave me the strikingly applicable nickname "-vvvv". /edit: by the way... The thing is that if you cut out all the comments, the function is too small to believe :)

Edited by SadBunny

Roses are FF0000, violets are 0000FF... All my base are belong to you.

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
Sign in to follow this  
Followers 0