Page 2 of 2

Re: StringBetween()

Posted: Sun Jul 17, 2022 7:12 pm
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.

Re: StringBetween()

Posted: Sun Jul 17, 2022 10:00 pm
by BarryG
I'm surprised that there wasn't a RegEx example in this topic.

Re: StringBetween()

Posted: Sun Jul 17, 2022 11:14 pm
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

Re: StringBetween()

Posted: Mon Jul 18, 2022 3:28 am
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

Re: StringBetween()

Posted: Mon Jul 18, 2022 9:02 am
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.

Re: StringBetween()

Posted: Mon Jul 18, 2022 10:38 am
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

Re: StringBetween()

Posted: Mon Jul 18, 2022 4:54 pm
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

Re: StringBetween()

Posted: Mon Jul 18, 2022 6:42 pm
by davido
@mk-soft,
Excellent. Very useful.
Thank you for sharing.

Re: StringBetween()

Posted: Thu Aug 25, 2022 3:30 pm
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