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. :D :D

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. :mrgreen:

TI-994A. 2nd version works perfectly for my needs. :D

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. :D

I had a go on https://regexr.com/ but soon gave up. :oops:

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
dcr3 wrote: Thu Aug 25, 2022 8:03 pm I had a go on https://regexr.com/ but soon gave up. :oops:
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 :wink:

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.