Page 1 of 3
How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 11:47 am
by dcr3
Hi. What is the best way to get the word_before and word_after a specific keyword
from a string.That meets these two conditions.
1. string.s="blah blah blah word_before keyword word_after blah blah blah"
2. string.s=" blah blah blah (word_before keyword word_after, blah blah blah "
wrd_before.s = word_before
wrd_after.s = word_after
Either with RegExp or any other method.
Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 11:53 am
by BarryG
Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 1:46 pm
by Olli
Be careful about space length in this method : only one char-space !
Code: Select all
a$ = "monday tuesday wednesday thuersday friday"
procedure.s before(a$, c$)
b$ = reverseString(a$)
procedurereturn reverseString(StringField(Mid(b$, FindString(b$, ReverseString(c$) ) ), 2, " ") )
endProcedure
procedure.s after(a$, c$)
procedurereturn stringField(Mid(a$, findString(a$, c$) ), 2, " ")
endprocedure
debug before(a$, "wednesday")
debug after(a$, "wednesday")
Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 1:59 pm
by mk-soft
Its very simple !?
Code: Select all
;-TOP by mk-soft, v1.01.0, 25.08.2022
Procedure.s StringBefore(String.s, StringToFind.s, StartPosition = 1, Mode = #PB_String_CaseSensitive)
Protected r1.s, pos.i
pos = FindString(String, StringToFind, StartPosition, Mode)
If pos
r1 = Left(String, pos - 1)
EndIf
ProcedureReturn r1
EndProcedure
Procedure.s StringAfter(String.s, StringToFind.s, StartPosition = 1, Mode = #PB_String_CaseSensitive)
Protected r1.s, pos.i
pos = FindString(String, StringToFind, StartPosition, Mode)
If pos
pos + Len(StringToFind)
r1 = Mid(String, pos)
EndIf
ProcedureReturn r1
EndProcedure
sVal.s = "blah blah blah word_before keyword word_after blah blah blah"
Debug "Before: " + StringBefore(sVal, " keyword ")
Debug "After: " + StringAfter(sVal, " keyword ")
Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 3:18 pm
by TI-994A
Another approach:
Code: Select all
source.s = "The quick brown fox jumped over the lazy dog."
key.s = "fox"
For i = 1 To CountString(source, " ") + 1
If StringField(source, i, " ") = key
keyIndex = i
Break
EndIf
Next
Debug "Word before: " + StringField(source, keyIndex - 1, " ")
Debug "Word after: " + StringField(source, keyIndex + 1, " ")
Just a rough POC though;
some error handling required.
Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 4:05 pm
by dcr3
Thank you Barry.
I came across that, when searching the forum.
Thank you Olli.
Thank you mk-soft.
Thank you TI-994A.
Works on the first string.
Not so on the second string.
dcr3 wrote: Thu Aug 25, 2022 11:47 am
That meets these two conditions.
1. string.s="blah blah blah word_before keyword word_after blah blah blah"
2. string.s=" blah blah blah (word_before keyword word_after, blah blah blah "
(word_before
word_after,
Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 4:31 pm
by infratec
Then you need to specify which characters can be inside of a word.
Why it should stop at ( and not at _
_ is also not a 'normal' letter.
So wee need to know what can be inside of a word.
Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 4:42 pm
by TI-994A
dcr3 wrote: Thu Aug 25, 2022 4:05 pm...Works on the first string.
Not so on the second string...
(word_before
word_after,
Validation checks are required to circumvent such issues. Again, here's just another POC, but it would require tweaking based on your own requirements. The trimming routine still fails if there are multiple non-alphanumeric characters appended to the words being trimmed.
Code: Select all
Procedure.s stripNonAlphaNum(raw.s)
For i = 33 To 47
raw = Trim(raw, Chr(i))
Next
For i = 58 To 64
raw = Trim(raw, Chr(i))
Next
For i = 91 To 96
raw = Trim(raw, Chr(i))
Next
For i = 123 To 126
raw = Trim(raw, Chr(i))
Next
ProcedureReturn raw
EndProcedure
source.s = " blah blah blah (word_before keyword word_after, blah blah blah "
key.s = "keyword"
For i = 1 To CountString(source, " ") + 1
If StringField(source, i, " ") = key
keyIndex = i
Break
EndIf
Next
If keyIndex > 1 ;to avoid checking position 0
Debug "Word before: " + stripNonAlphaNum(StringField(source, keyIndex - 1, " "))
EndIf
Debug "Word after: " + stripNonAlphaNum(StringField(source, keyIndex + 1, " "))
Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 5:06 pm
by Allen
Hi,
My attempt:
Code: Select all
EnableExplicit
Procedure.s WordSearch(String$,Key$,Mode.i)
Protected.i StartPos,EndPos,Tmp,SearchPos
Protected.s Tmp$
#Before=0
#After=1
EndPos=FindString(String$,Key$)
If EndPos
If Mode=#Before
SearchPos=1
StartPos=EndPos
Repeat
Tmp=FindString(String$," ",SearchPos)
If Tmp>=EndPos Or Tmp=0
ProcedureReturn Mid(String$,StartPos,EndPos-StartPos)
Else
StartPos=Tmp+1
SearchPos=StartPos
EndIf
ForEver
EndIf
If Mode=#After
EndPos=FindString(String$,Key$)
SearchPos=EndPos+Len(Key$)
Tmp=FindString(String$," ",SearchPos)
If Tmp>0
ProcedureReturn Mid(String$,SearchPos,Tmp-SearchPos)
EndIf
EndIf
EndIf
ProcedureReturn ""
EndProcedure
Define.s string$
string$="blah blah blah (word_before keyword word_after blah blah blah"
Debug "WordBefore: " +WordSearch(string$," keyword ",#Before) ;
Debug "WordAfter: "+WordSearch(string$, " keyword ",#After) )
Please note that the space before and after the 'keyword' is consider part of the keyword.
Allen
Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 5:07 pm
by dcr3
Thank you TI-994A.
That meets both criteria.
Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 5:33 pm
by dcr3
Thank you Allen.
That doesn't meet the condition on the second string.
TI-994A. 2nd version works perfectly for my needs.

Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 7:13 pm
by ChrisR
Another one with a Regular Expression
(\w = Matches letters, numbers and underscores)
Code: Select all
source.s = " blah blah blah (word_before keyword word_after, blah blah blah "
;source.s = " blah blah -(word_before keyword word_after!. blah blah ,word_before2 keyword word_after2. blah blah"
key.s = "keyword"
If CreateRegularExpression(0, "(\w+)\s*" + key+ "\s*(\w+)")
If ExamineRegularExpression(0, source)
While NextRegularExpressionMatch(0)
;Debug "Match: " + RegularExpressionMatchString(0)
Debug "Word_before: " + RegularExpressionGroup(0, 1)
Debug "Word_after: " + RegularExpressionGroup(0, 2)
Wend
EndIf
FreeRegularExpression(0)
Else
Debug RegularExpressionError()
EndIf
Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Thu Aug 25, 2022 8:03 pm
by dcr3
Thank you ChrisR.
That also works great.
I had a go on
https://regexr.com/ but soon gave up.

Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Fri Aug 26, 2022 10:10 am
by ChrisR
I don't use RegEx more than that, despite its huge capabilities.
But it's not so easy, it requires experience, which I don't have, or googling to find the right expression syntax.
The example was just here to show another possible way to do it. If it was for me, I don't think I would use it either

Re: How to get the word_before and word_after a specific keyword from a string.
Posted: Fri Aug 26, 2022 1:20 pm
by infratec
Ok, my version:
Code: Select all
EnableExplicit
Structure WordBeforeAfter_Structure
Before$
After$
EndStructure
Procedure.i GetWordBeforeAndAfter(String$, Keyword$, List ResultList.WordBeforeAfter_Structure())
Protected.i ElementAlreadyAdded, Pos
Protected Word$
Protected *Ptr.Character, *End
ClearList(ResultList())
*End = @String$ + (SizeOf(Character) * Len(String$))
Pos = FindString(String$, Keyword$)
While Pos
ElementAlreadyAdded = #False
Word$ = ""
*Ptr = @String$ + (SizeOf(Character) * (Pos + Len(Keyword$) - 1))
If *Ptr\c = ' '
*Ptr + SizeOf(Character)
While (*Ptr\c >= 'A' And *Ptr\c <= 'Z') Or (*Ptr\c >= '_' And *Ptr\c <= 'z') And *Ptr <= *End
Word$ + Chr(*Ptr\c)
*Ptr + SizeOf(Character)
Wend
AddElement(ResultList())
ResultList()\After$ = Word$
ElementAlreadyAdded = #True
EndIf
Word$ = ""
*Ptr = @String$ + (SizeOf(Character) * (Pos - 2))
If *Ptr\c = ' '
*Ptr - SizeOf(Character)
While (*Ptr\c >= 'A' And *Ptr\c <= 'Z') Or (*Ptr\c >= '_' And *Ptr\c <= 'z') And *Ptr >= @String$
Word$ = Chr(*Ptr\c) + Word$
*Ptr - SizeOf(Character)
Wend
If Not ElementAlreadyAdded
AddElement(ResultList())
EndIf
ResultList()\Before$= Word$
EndIf
Pos = FindString(String$, Keyword$, Pos + 1)
Wend
ProcedureReturn ListSize(ResultList())
EndProcedure
NewList WordBeforeAfterList.WordBeforeAfter_Structure()
If GetWordBeforeAndAfter(" blah blah -(word_before keyword word_after!. blah blah ,word_before_ keyword word_after_. blah blah", "keyword", WordBeforeAfterList())
;If GetWordBeforeAndAfter(" blah blah -(word_before keyword word_after", "keyword", WordBeforeAfterList())
;If GetWordBeforeAndAfter("word_before keyword word_after", "keyword", WordBeforeAfterList())
;If GetWordBeforeAndAfter("keyword word_after", "keyword", WordBeforeAfterList())
;If GetWordBeforeAndAfter("keyword", "keyword", WordBeforeAfterList())
ForEach WordBeforeAfterList()
Debug WordBeforeAfterList()\Before$
Debug WordBeforeAfterList()\After$
Next
EndIf
Without RegEx and with pointers.