Find a substring in between 2 other substrings

Post your working scripts, libraries and tools for AHK v1.1 and older
Hotte
Posts: 32
Joined: 03 Jan 2018, 14:39

Find a substring in between 2 other substrings

06 Jun 2018, 12:25

Hi,
this is not the same as Instr(). It is a new function for easy string-in-between-strings search.

Best illustration is examples:

a := "the big brown fox jumps over the lazy dog"
msgbox % partStr(a,"fox","over") returns "jumps" - no leading or trailing spaces
msgbox % partStr(a,,"brown") returns "the big"
msgbox % partStr(a,"the") returns "big brown fox jumps over the lazy dog" - first 'the'
msgbox % partStr(partStr(a,"the"),"the") returns "lazy dog" ;)

Multiline strings are ok. Leading/trailing tabs and spaces are not being returned. Trailing CR,LF are not being returned, i.e. returned strings always end at line-end.
a:= "the big`nbrown`nfox jumps`r`nover the lazy dog"
msgbox % partStr(a,"brown") returns "`nfox jumps"
msgbox % partStr(a,"brown`n") returns "fox jumps"

You can achieve the same with quite some SubStr/Instr effort. Or you can try this easy-to-go function.

by Hotte

Code: Select all

partStr(text, starttext := "", endtext := "")
{	if (starttext = "")
		iv := 1
	else
	{	iv := Instr(text,starttext)
    	if not iv
        	Return ""
    	iv := iv + StrLen(starttext)
    }
    if (endtext = "") or not Instr(text,endtext,false,iv + 1)
    {	ib := Instr(text,chr(13),,iv)
		if ib
        	ib := ib - 1
        else
        {	ib := Instr(text,chr(10),,iv)
       		if ib
            	ib := ib - 1
            else
        		ib := StrLen(text)
        }
	}
    else
    	ib := Instr(text,endtext,false,iv + 1) - 1

    Return Trim(SubStr(text,iv,ib-iv+1)," `t")
}
Last edited by Hotte on 06 Jun 2018, 13:07, edited 1 time in total.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Find a substring in between 2 other substrings

06 Jun 2018, 12:48

Hi :wave:.
Cool idea :thumbup: . There is an error in the example: msgbox % partStr((partStr,"the"),"the") ; returns "lazy dog" ;), should be msgbox % partStr(partStr(a,"the"),"the") ; returns "lazy dog" ;)

I tried to make a regex verison,

Code: Select all

partStr2(byref str, a := "", b := "", caseSensitive := false, trim := "`n`r`t "){
	l := a == "" ? "^" : "(?<=\Q" a "\E)"
	r := b == "" ? "$" : "(?=\Q" b "\E)"
	regexmatch(str, (caseSensitive ? "" : "i") . "`amO)" . l ".*?" . r, o)
	return trim != "" ? trim(o[0], trim) : o[0]
}
; example
a := "the big brown fox jumps over the lazy dog"
msgbox % partStr2(a,"fox","over") ; returns "jumps" - no leading or trailing spaces
msgbox % partStr2(a,,"brown") ; returns "the big" 
msgbox % partStr2(a,"the") ; returns "big brown fox jumps over the lazy dog" - first 'the'
msgbox % partStr2(partStr2(a,"the"),"the") ; returns "lazy dog" ;) 
Thanks for sharing, cheers.
Last edited by Helgef on 09 Jun 2018, 13:22, edited 2 times in total.
Hotte
Posts: 32
Joined: 03 Jan 2018, 14:39

Re: Find a substring in between 2 other substrings

06 Jun 2018, 13:09

Wow, I have always admired the heroes of RegEx coding. It would probably take me 2 days to understand, and 2 others to put it in RegEx.
So many thanks for this! :clap:

Edit
Just be clear that partStr2 handles multiline strings differently: If you want CR,LF to be ignored go for partStr2.
If you want the resulting string to always end before the next CR,LF go for partStr.
It's nice to have two solutions!

Just corrected the error in my example.
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: Find a substring in between 2 other substrings

08 Jun 2018, 06:26

Nice I will try this thanks.
What seems great about this is that you can choose a word rather than count the string begining pos and ending pos
Hotte
Posts: 32
Joined: 03 Jan 2018, 14:39

Re: Find a substring in between 2 other substrings

08 Jun 2018, 15:15

Exactly. That is what it was supposed to do: An non-technical approach to strings or to analyse tagged text.
Originally I wrote it to read a table of technical specifications. Something like:

Code: Select all

t := "Rate: 100 bits/s`nFormat: 1920 x 1080`nColor-depth: 10 bits`nNo of audio channels: 5`nCompression: h.264"

ch := partStr(t,"channels:") ; returns "5"
col := partStr(t,"depth:","bits")	; returns "10"
width := partStr(t,"Format:","x") ; returns "1920"
height := partStr(partStr(t,"Format:"),"x")	; returns "1080"
Easy.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Find a substring in between 2 other substrings

09 Jun 2018, 02:24

Thanks for the follow up example and pointing out the line break differences. I corrected an unrelated error in my code.

Cheers.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Find a substring in between 2 other substrings

09 Jun 2018, 03:01

Btw:
simplest way to make a RegEx needle literal? - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=30420
vNeedle := "\Q" RegExReplace(vNeedle, "\\E", "\E\\E\Q") "\E"
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Find a substring in between 2 other substrings

09 Jun 2018, 03:06

Greetings.
You wouldn't use that on the needle, but no the literal text, that is a and b in my code.

Edit:
jeeswg wrote:Yes? No?
Yes!
Last edited by Helgef on 10 Jun 2018, 07:48, edited 1 time in total.
garry
Posts: 3758
Joined: 22 Dec 2013, 12:50

Re: Find a substring in between 2 other substrings

09 Jun 2018, 08:38

@Helgef, I had a small problem with last example ( because `n ) , this was ok :

Code: Select all

transform,s,chr,10
t     := "Rate: 100 bits/s`nFormat: 1920 x 1080`nColor-depth: 10 bits`nNo of audio channels: 5`nCompression: h.264"
ch    := partStr2(t,"channels:",s)              ; returns "5"
col   := partStr2(t,"depth:","bits")	        ; returns "10"
width := partStr2(t,"Format:","x")              ; returns "1920"
height:= partStr2(partStr2(t,"Format:"),"x",s)	; returns "1080"
msgbox,%ch%`n%col%`n%width%`n%height%
return
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Find a substring in between 2 other substrings

09 Jun 2018, 13:22

Thank you garry. I think adding `am to the needle options will give a more preferable result, still, this will not make partstr2 behave exactly as partstr. I will update the code anyways.

Cheers.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Find a substring in between 2 other substrings

09 Jun 2018, 13:38

Yes? No?

Code: Select all

;before:
	l := a == "" ? "^" : "(?<=\Q" a "\E)"
	r := b == "" ? "$" : "(?=\Q" b "\E)"

;after:
	a := RegExReplace(a, "\\E", "\E\\E\Q")
	b := RegExReplace(b, "\\E", "\E\\E\Q")
	l := a == "" ? "^" : "(?<=\Q" a "\E)"
	r := b == "" ? "$" : "(?=\Q" b "\E)"
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: Chunjee and 60 guests