StringBetween()

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
AZJIO
Addict
Addict
Posts: 2141
Joined: Sun May 14, 2017 1:48 am

Re: StringBetween()

Post by AZJIO »

bgeraghty wrote: Sun Jul 17, 2022 3:59 pm I like the idea of using StringField() for this, didn't think of that.
StringField() - not economical.
BarryG wrote: Sun Jul 17, 2022 1:51 am

Code: Select all

  l=FindString(text$,left$)
  r=FindString(text$,right$,l+1)
If the first lookup fails, then the second lookup is not necessary.
BarryG
Addict
Addict
Posts: 4121
Joined: Thu Apr 18, 2019 8:17 am

Re: StringBetween()

Post by BarryG »

I'm surprised that there wasn't a RegEx example in this topic.
Little John
Addict
Addict
Posts: 4774
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: StringBetween()

Post by Little John »

BarryG wrote: Sun Jul 17, 2022 10:00 pm I'm surprised that there wasn't a RegEx example in this topic.
Here you go! :-)

Code: Select all

; PB 6.00 LTS

EnableExplicit

Procedure.i StringBetween (source$, before$, after$, Array found$(1))
   ; keywords for getting more information: positive lookbehind, positive lookahead, metacharacters, repetition, laziness
   Protected.i regEx, nFound
   
   regEx = CreateRegularExpression(#PB_Any, "(?<="+before$+").*?(?="+after$+")", #PB_RegularExpression_DotAll|#PB_RegularExpression_NoCase)
   nFound = ExtractRegularExpression(regEx, source$, found$())
   FreeRegularExpression(regEx)
   
   ProcedureReturn nFound
EndProcedure


Define source$, before$, after$, n.i, i.i
Dim found$(0)

source$ = "<b>1st bold</b> expression, <b>2nd bold</b> expression, <b>3rd bold</b> expression"
before$ = "<b>" : after$ = "</b>"

n = StringBetween(source$, before$, after$, found$())
For i = 0 To n-1
   Debug "'" + found$(i) + "'"
Next
AZJIO
Addict
Addict
Posts: 2141
Joined: Sun May 14, 2017 1:48 am

Re: StringBetween()

Post by AZJIO »

BarryG wrote: Sun Jul 17, 2022 10:00 pm I'm surprised that there wasn't a RegEx example in this topic.
Increases the file size by 150-200 kb
BarryG
Addict
Addict
Posts: 4121
Joined: Thu Apr 18, 2019 8:17 am

Re: StringBetween()

Post by BarryG »

AZJIO wrote: Sun Jul 17, 2022 7:12 pmIf the first lookup fails, then the second lookup is not necessary.
True! That was very old code that I wrote that I hadn't revisited for years (until this topic). I've amended it based on your comment:

Code: Select all

Procedure.s PluckString(text$,left$,right$)
  l=FindString(text$,left$)
  If l
    r=FindString(text$,right$,l+1)
    If r
      p$=Mid(Left(text$,r-1),l+Len(left$))
    EndIf
  EndIf
  ProcedureReturn p$
EndProcedure
But I have a question: How can I make the following code return just "1", if the text before and after it changes?

Code: Select all

Procedure.s PluckString(text$,left$,right$)
  l=FindString(text$,left$)
  If l
    r=FindString(text$,right$,l+1)
    If r
      p$=Mid(Left(text$,r-1),l+Len(left$))
    EndIf
  EndIf
  ProcedureReturn p$
EndProcedure

random$=Str(Random(999,100)) ; Will be "100" to "999".
string$="<italic>Value</italic><"+random$+">1 AUD</"+random$+">"
Debug PluckString(string$, ">", " AUD") ; Want just "1" returned.
User avatar
ar-s
Enthusiast
Enthusiast
Posts: 344
Joined: Sat Oct 06, 2007 11:20 pm
Location: France

Re: StringBetween()

Post by ar-s »

My contribution when there are several occurrences.

Code: Select all

Declare.b StringBetween(String$, StartString$, EndString$)
Global NewList Strings.s()

Procedure.b StringBetween(String$, StartString$, EndString$)
    Protected N = 0, S1=0, E1=0, P1=0, P2=0
    ClearList(Strings())
    S1 = CountString(String$, StartString$)
    E1 = CountString(String$, EndString$)
    
    If S1 > 0 And E1 >0
        N+1    
    EndIf
    
    If N = 0
        ProcedureReturn 0 
    ElseIf S1 > E1
        N = S1
    Else
        N = E1
    EndIf
    
    POS = 0
    For i = 0 To N-1
        P1 = FindString(string$, StartString$, POS) : P2 = FindString(string$, EndString$, POS)
        res$ = Mid(string$,P1+Len(StartString$),P2-(P1+Len(StartString$)))
        If Len(res$)>0
            AddElement( Strings() )
            Strings() = res$
        EndIf
        POS = p2+Len(EndString$)
    Next
    
    ProcedureReturn 1

EndProcedure

; ======= Example =========

T$ = "<title>Find me : title</title> Hello world <title>Catch me</title>"
If StringBetween(T$, "<title>", "</title>")
    ForEach Strings()
        Debug Strings()
    Next
    
Else
    
    Debug "no result"
    
EndIf
~Ar-S~
My Image Hoster for PB users
My webSite (french) with PB apps : LDVMULTIMEDIA
PB - 3.x / 5.7x / 6 - W11 x64 - Ryzen 7 3700x / #Rpi4

Code: Select all

r3p347 : 7ry : un71l d0n3 = 1
User avatar
mk-soft
Always Here
Always Here
Posts: 6202
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: StringBetween()

Post by mk-soft »

Code: Select all

;-TOP by mk-soft

Procedure StringBetweenList(String.s, Left.s, Right.s, List Result.s())
  Protected pos1, pos2, len1, len2
  
  ClearList(Result())
  len1 = Len(Left)
  len2 = Len(Right)
  
  Repeat
    pos1 = FindString(String, Left, pos1)
    If pos1
      pos1 + len1
      pos2 = FindString(String, Right, pos1)
      If pos2
        AddElement(Result())
        Result() = Mid(String, pos1, pos2 - pos1)
        pos1 = pos2 + len2
      Else
        Break
      EndIf
    Else
      Break
    EndIf
  ForEver
  ProcedureReturn ListSize(Result())
  
EndProcedure

; ======= Example =========

Define NewList r1.s()

text.s = "<title>Find me : title</title><title>Hello world!</title> DATA 123456789 <title>Catch me</title><title>Error missing end"
Define cnt = StringBetweenList(text, "<title>", "</title>", r1())
Debug "Count = " + cnt
ForEach r1()
  Debug r1()
Next
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
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: StringBetween()

Post by davido »

@mk-soft,
Excellent. Very useful.
Thank you for sharing.
DE AA EB
Allen
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Nov 10, 2021 2:05 am

Re: StringBetween()

Post by Allen »

Hi,
BarryG wrote: Mon Jul 18, 2022 9:02 am
AZJIO wrote: Sun Jul 17, 2022 7:12 pmIf the first lookup fails, then the second lookup is not necessary.
True! That was very old code that I wrote that I hadn't revisited for years (until this topic). I've amended it based on your comment:

Code: Select all

Procedure.s PluckString(text$,left$,right$)
  l=FindString(text$,left$)
  If l
    r=FindString(text$,right$,l+1)
    If r
      p$=Mid(Left(text$,r-1),l+Len(left$))
    EndIf
  EndIf
  ProcedureReturn p$
EndProcedure
But I have a question: How can I make the following code return just "1", if the text before and after it changes?

Code: Select all

Procedure.s PluckString(text$,left$,right$)
  l=FindString(text$,left$)
  If l
    r=FindString(text$,right$,l+1)
    If r
      p$=Mid(Left(text$,r-1),l+Len(left$))
    EndIf
  EndIf
  ProcedureReturn p$
EndProcedure

random$=Str(Random(999,100)) ; Will be "100" to "999".
string$="<italic>Value</italic><"+random$+">1 AUD</"+random$+">"
Debug PluckString(string$, ">", " AUD") ; Want just "1" returned.
My attempt to solve this question.

Code: Select all

EnableExplicit

Procedure.s PluckString(String$,Start$,End$)
  Protected.i StartPos,EndPos,Tmp
  Protected.s Tmp$
  EndPos=FindString(String$,End$)
  If EndPos
    Tmp$=Left(String$,EndPos-1)
    StartPos=0
    Repeat
      Tmp=FindString(Tmp$,Start$,StartPos)
      If Tmp=0
        ProcedureReturn Mid(Tmp$,StartPos)
      Else
        StartPos=Tmp+1
      EndIf
    ForEver
  EndIf
  ProcedureReturn ""
EndProcedure
  
Define.s random$,string$
random$=Str(Random(999,100)) ; Will be "100" to "999".
string$="<italic>Value</italic><"+random$+">1 AUD</"+random$+">"
Debug PluckString(string$, ">", " AUD") ; Want just "1" returned.
Allen
Post Reply