return pattern matches with pcre

General FreeBASIC programming questions.
Posts: 19
Joined: Oct 27, 2008 15:50

return pattern matches with pcre

Postby applepi » Feb 05, 2009 8:42

i am trying the pcre_demo.bas example in the freebasic regex examples
it is working well , but it returns the first pattern match only
in perl we can use something like /.../g to return every match
are there any special parameters we can supply to force returning all the matches?? in the example below it must match two "foo"'s in the string "fooXCR foo" , but it returns only the first one ,what should i do

Code: Select all

'' PCRE example, translated by jofers (spam[at]

#include once "pcre/"

dim OVECCOUNT as const uinteger = 30    '' should be a multiple of 3

   dim as pcre ptr re
   dim as zstring ptr error_
   dim as integer erroffset
   dim as integer ovector(OVECCOUNT-1)
   dim as integer rc, i
   dim as string pattern, buffer
   pattern = "foo"
   buffer = "fooXCR foo"
   '' compile the regular expression
   re = pcre_compile( pattern,         _ ''   the pattern
                  0,               _ ''   default options
                  @error_,         _ ''   for error message
                  @erroffset,      _ ''   for error offset
                  NULL )           _ ''   use default character tables
   '' compilation failed: print the error message and exit
   if re = NULL then
      print "pcre compilation failed at offset "; str(erroffset); ": "; *error_
   end if
   '' compilation succeeded: match the subject
   rc = pcre_exec( re,                 _ '' the compiled pattern
               NULL,               _ '' no extra data - we didn't study the pattern
               buffer,              _ '' the subject string
               len( buffer ),      _ '' the length of the subject
               0,                  _ '' start at offset 0 in the subject
               0,                  _ '' default options
               @ovector(0),        _ '' output vector for substring information
               OVECCOUNT )         _ '' number of elements in the output vector
   '' matching failed: handle error cases
   if rc < 0 then
       select case rc
       case pcre_error_nomatch
           print "no match"
       'handle other special cases if you like
       case else
          print "matching error"; rc
       end select
   end if
   '' match succeded
   print "match succeeded"
   print "rc = " & rc
   '' the output vector wasn't big enough
   if rc = 0 then
      rc = OVECCOUNT \ 3
      print "ovector only has room for"; rc-1; " captured substrings"
   end if
   '' show substrings stored in the output vector
   dim as zstring ptr substring_start 
   dim as integer substring_length
   for i = 0 to rc-1
       substring_start = @buffer[ovector(2*i)]
       substring_length = ovector(2*i+1) - ovector(2*i)
       print i; ": "; mid(buffer, ovector(2*i)+1, substring_length)
       Print substring_length

Posts: 1525
Joined: May 27, 2005 17:18

Postby jofers » Feb 07, 2009 18:03

Yeah, Perl is pretty good for that sort of thing. Unfortunately, though you can only do one search at a time. However, you do have the option of starting midway through the string, so you find all your matches in a loop:

Code: Select all

#include once "pcre/"
#define OVECCOUNT 30

' Compile pattern
Dim As ZString Ptr error_
Dim As ZString Ptr substring_start
Dim As Integer substring_length
Dim As Integer erroffset
Dim As Integer rc, i, j
Dim As Integer ovector(OVECCOUNT-1)

Dim As pcre Ptr re = pcre_compile( "foo", 0, @error_, @erroffset, NULL )
Dim As ZString * 64 buffer = " foo other foo "

If re = NULL Then
    Print "pcre compilation failed at offset "; Str(erroffset); ": "; *error_
End If
' List all matches
    rc = pcre_exec( re, NULL, buffer, Len( buffer ), j, 0, @ovector(0), OVECCOUNT )

    ' matching failed: handle error cases
    If rc > 0 Then
        For i = 0 To rc - 1
            substring_start = @buffer[ovector(2*i)]
            substring_length = ovector(2*i+1) - ovector(2*i)
            Print i; ": "; Mid(buffer, ovector(2*i)+1, substring_length); " "; substring_length
            j += substring_length + ovector(2*i)
        Next i

    ElseIf rc = 0 Then
        rc = OVECCOUNT \ 3
        Print "ovector only has room for"; rc-1; " captured substrings"

        If rc = PCRE_ERROR_NOMATCH Then
            Print "No match found"
            Print "Matching error", rc, PCRE_ERROR_NOMATCH
        End If
    End If
Loop While rc >= 0

Return to “General”

Who is online

Users browsing this forum: No registered users and 3 guests