sorry I didn't mean to sound harsh. Olli had your back and gave me a good kicking!Oso wrote: Sat Aug 27, 2022 10:03 pmI've got ya, my apologies for 'throwing the spanner in the works', as they sayidle wrote: Sat Aug 27, 2022 2:27 am @Oso you've just taken 2 steps back, each post was an improvement over the others, my post also simplified and improved the runtime complexity of Infratec's last code, he's a PB guru, he knows his stuff.![]()
How to get the word_before and word_after a specific keyword from a string.
Re: How to get the word_before and word_after a specific keyword from a string.
Re: How to get the word_before and word_after a specific keyword from a string.
Could not miss the party
Code:

Code:
Code: Select all
EnableExplicit
Structure STRING_BA_STRUCT
before.s
after.s
EndStructure
Procedure.i StringBeforeAndAfter(*Str,Signature.s,*StrBA.STRING_BA_STRUCT)
Protected *src.Unicode
Protected *sig.Unicode
Protected *a.Unicode
Protected *b.Unicode
Protected *c.Unicode
*src = *str
*sig = @Signature
Repeat
If *src\u = *sig\u
*a = *src
Repeat
*src + 2
*sig + 2
If *src\u <> *sig\u
Break
EndIf
Until *sig\u = #Null Or *src\u = #Null
If *sig\u = #Null
*b = *src - *a
*b + *a
*c = *a - 4
If *a < *Str Or *b\u = #Null
ProcedureReturn #False
EndIf
*a + Bool(*a\u = ' ') * 4
*b + Bool(*b\u = ' ') * 2
*sig = #Null
Repeat
*sig + Bool(*c\u & $30 = $30 And *c\u < $3A)
*sig + Bool(*c\u & $40 = $40 And *c\u <> $40 And *c\u < $5B)
*sig + Bool(*c\u & $60 = $60 And *c\u <> $60 And *c\u < $7B)
*sig + Bool(*c\u = '_')
If *sig = #Null
Break
EndIf
*c - 2
*sig = 0
Until *c = *Str
If *sig = 0
*c + 2
EndIf
*a\u = #Null
*StrBA\before = PeekS(*c,(*a - *c - (Bool(*a\u = ' ') * 2)) >> 1)
*c = *b
*sig = #Null
Repeat
*sig + Bool(*c\u & $30 = $30 And *c\u < $3A)
*sig + Bool(*c\u & $40 = $40 And *c\u <> $40 And *c\u < $5B)
*sig + Bool(*c\u & $60 = $60 And *c\u <> $60 And *c\u < $7B)
*sig + Bool(*c\u = '_')
If *sig = #Null
Break
EndIf
*c + 2
*sig = 0
Until *c\u = #Null
*StrBA\after = PeekS(*b,(*c - *b) >> 1)
ProcedureReturn #True
EndIf
*sig = @Signature
*src = *Str
EndIf
*src + 2
Until *src\u = #Null
ProcedureReturn #False
EndProcedure
Procedure.i Main()
Protected str1.s
Protected str2.s
Protected str.STRING_BA_STRUCT
str1 = "blah blah blah word_before keyword word_after blah blah blah"
str2 = " blah blah blah (word_before keyword word_after, blah blah blah "
StringBeforeAndAfter(@str1,"keyword",@str)
Debug str\before
Debug str\after
StringBeforeAndAfter(@str2,"keyword",@str)
Debug str\before
Debug str\after
;works with and without spaces after the keyword!
str1 = "blah blah blah word_beforekeywordword_after blah blah blah"
str2 = " blah blah blah (word_beforekeywordword_after, blah blah blah "
StringBeforeAndAfter(@str1,"keyword",@str)
Debug str\before
Debug str\after
StringBeforeAndAfter(@str2,"keyword",@str)
Debug str\before
Debug str\after
ProcedureReturn #Null
EndProcedure
Main()
End
Re: How to get the word_before and word_after a specific keyword from a string.
Hi,
The shortest(slow) version? idea from Olli and Oso.
Allen
Edit:
was: Debug "Word After : "+RTrim(StringField(ReverseString(StringField(ReverseString(String),1,ReverseString(KeyWord))),1," "),",")
is : Debug "Word After : "+RTrim(StringField(StringField(String,2,KeyWord),1," "),",")
The shortest(slow) version? idea from Olli and Oso.

Code: Select all
Keyword.s=" keyword "
string.s="blah blah blah word_before keyword word_after blah blah blah"
Debug String
Debug "Word Before : "+LTrim(ReverseString(StringField(ReverseString(StringField(String,1,Keyword)),1," ")),"(")
Debug "Word After : "+RTrim(StringField(StringField(String,2,KeyWord),1," "),",")
string.s=" blah blah blah (word_before keyword word_after, blah blah blah "
Debug String
Debug "Word Before : "+LTrim(ReverseString(StringField(ReverseString(StringField(String,1,Keyword)),1," ")),"(")
Debug "Word After : "+RTrim(StringField(StringField(String,2,KeyWord),1," "),",")
Edit:
was: Debug "Word After : "+RTrim(StringField(ReverseString(StringField(ReverseString(String),1,ReverseString(KeyWord))),1," "),",")
is : Debug "Word After : "+RTrim(StringField(StringField(String,2,KeyWord),1," "),",")
Re: How to get the word_before and word_after a specific keyword from a string.
Code: Select all
Macro WordBefore(string, keyword, separator = " ")
StringField(StringField(string, 1, keyword), CountString(StringField(string, 1, keyword), sep), sep)
EndMacro
Macro WordAfter(string, keyword, separator = " ")
StringField(Trim(StringField(String, 2, keyword)), 1, sep)
EndMacro
string.s = "blah blah blah word_before keyword word_after blah blah blah"
keyword.s = "keyword"
sep.s = " "
Debug WordBefore(string, keyword, sep)
Debug WordAfter(string, keyword, sep)
Re: How to get the word_before and word_after a specific keyword from a string.
A strange way to get the word before...
okey, enough from me.
Code: Select all
Macro BeforeWord(String, Keyword, Separator = " ")
GetExtensionPart(ReplaceString(Trim(StringField(string, 1, keyword)), sep, "."))
EndMacro
Re: How to get the word_before and word_after a specific keyword from a string.

GetExtensionPart() option is very researched to do this task. I think everybody has won here, each one with a different approach.
I say a "hello" to Mijikai who shew me recently this easy method of *x.character\c and certainly who learnt it by another one again, as a humain string.
I thank infratec who knows the subject perfectly.
I say a hello too to ChrisR I often read to give an idea also[/b].
And I thank to everybody to share and share again.
I think I have a other approach. (It stays myself any teeth


I imagine a search where each character is counted and referring depending its place in the string. It wastes lots of memory also, but it is quick and usable everywhere in a data base.