How to get the word_before and word_after a specific keyword from a string.

Just starting out? Need help? Post your questions and find answers here.
dcr3
Enthusiast
Enthusiast
Posts: 181
Joined: Fri Aug 04, 2017 11:03 pm

How to get the word_before and word_after a specific keyword from a string.

Post 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.
Olli
Addict
Addict
Posts: 1202
Joined: Wed May 27, 2020 12:26 pm

Re: How to get the word_before and word_after a specific keyword from a string.

Post 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")
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to get the word_before and word_after a specific keyword from a string.

Post 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 ")

My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
TI-994A
Addict
Addict
Posts: 2704
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: How to get the word_before and word_after a specific keyword from a string.

Post 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.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
dcr3
Enthusiast
Enthusiast
Posts: 181
Joined: Fri Aug 04, 2017 11:03 pm

Re: How to get the word_before and word_after a specific keyword from a string.

Post 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,
infratec
Always Here
Always Here
Posts: 7588
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: How to get the word_before and word_after a specific keyword from a string.

Post 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.
User avatar
TI-994A
Addict
Addict
Posts: 2704
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: How to get the word_before and word_after a specific keyword from a string.

Post 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, " "))
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
Allen
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Nov 10, 2021 2:05 am

Re: How to get the word_before and word_after a specific keyword from a string.

Post 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
Last edited by Allen on Thu Aug 25, 2022 5:13 pm, edited 1 time in total.
dcr3
Enthusiast
Enthusiast
Posts: 181
Joined: Fri Aug 04, 2017 11:03 pm

Re: How to get the word_before and word_after a specific keyword from a string.

Post by dcr3 »

Thank you TI-994A. :D :D

That meets both criteria.
dcr3
Enthusiast
Enthusiast
Posts: 181
Joined: Fri Aug 04, 2017 11:03 pm

Re: How to get the word_before and word_after a specific keyword from a string.

Post 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
User avatar
ChrisR
Addict
Addict
Posts: 1466
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: How to get the word_before and word_after a specific keyword from a string.

Post 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
dcr3
Enthusiast
Enthusiast
Posts: 181
Joined: Fri Aug 04, 2017 11:03 pm

Re: How to get the word_before and word_after a specific keyword from a string.

Post by dcr3 »

Thank you ChrisR.

That also works great. :D

I had a go on https://regexr.com/ but soon gave up. :oops:
User avatar
ChrisR
Addict
Addict
Posts: 1466
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: How to get the word_before and word_after a specific keyword from a string.

Post 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:
infratec
Always Here
Always Here
Posts: 7588
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: How to get the word_before and word_after a specific keyword from a string.

Post 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.
Post Reply