3

I have a URL string and need to get certain word from a match.

Example:

/school/student/studentname1/detail/55/address/address1

I am able to pass to fetch detail of the needed one like,

local s1,s2,s3 =myString:match("/school/student/(.-)/detail/(.-)/address/(.-)")

Now the problem is that my string can be

myString = /school/student/studentname1

or

myString = /school/student/studentname1/detail/55

In that case my regex is failing, any help ?

2
  • It looks like sometimes there can be no details nor addresses, what do you want to happen then? Commented Aug 16, 2018 at 5:45
  • @CertainPerformance I am trying to make regex in such a way that it matches all the condition (ie match all 3 values or match only 2 values or match only 1 value) and if matches detail or address then s2 and s3 will have value if not s2 and s3 will not have value Commented Aug 16, 2018 at 6:33

3 Answers 3

3
local all_fields = { student = 1, detail = 2, address = 3 }

local function parse(str)
   local info = {}
   local index
   for w in str:gmatch"/([^/]+)" do
      if index then
         info[index] = w
         index = nil
      else
         index = all_fields[w]
      end
   end
   return (table.unpack or unpack)(info, 1, 3)
end

local myString = '/school/student/studentname1/detail/55/address/address1'
local s1, s2, s3 = parse(myString)
print(s1, s2, s3)

myString = '/school/student/studentname1/address/address1'
s1, s2, s3 = parse(myString)
print(s1, s2, s3)

myString = '/school/student/studentname1/detail/55'
s1, s2, s3 = parse(myString)
print(s1, s2, s3)
Sign up to request clarification or add additional context in comments.

Comments

2

To begin with, your original patter was not working as expected since it did not capture the address (because you used .- which is not greedy)

So one way to fix the original patter could be using /school/student/([^/]+)/detail/([^/]+)/address/([^/]+)

where [^/] means any character except /

Then, in order to optionally match some options and since lua patterns does not allow optional groups, you may need to use several steps like this:

myString = "/school/student/studentname1/detail/55"
local s1,s2,s3
s1 =myString:match("/school/student/([^/]+)")
if (s1 ~= nil) then
  print(s1)
  s2 =myString:match("/detail/([^/]+)")
  if (s2 ~= nil) then
    print(s2)
    s3 =myString:match("/address/([^/]+)")
    if (s3 ~= nil) then
      print(s3)
    end
  end
end

Finally, if you want to make sure that detail and address appear exactly on that order, you may use this:

myString = "/school/student/studentname1/address/myaddress"
local s1,s2,s3
s1 =myString:match("/school/student/([^/]+)")
if (s1 ~= nil) then
  print(s1)
  s1,s2 =myString:match("/school/student/([^/]+)/detail/([^/]+)")
  if (s2 ~= nil) then
    print(s2)
    s1,s2,s3 =myString:match("/school/student/([^/]+)/detail/([^/]+)/address/([^/]+)")
    if (s3 ~= nil) then
      print(s3)
    end
  end
end

That way it will find /school/student/studentname1/detail/55 but it will not find /school/student/studentname1/address/myaddress. If you don't need it like this, just use the first version.

Comments

2

This is the best one-liner I could come up with:

local s1,s2,s3 =myString:match("/[^/]+/[^/]+/([^/]+)/?[^/]*/?([^/]*)/?[^/]*/?([^/]*)")

Demo

Explanation:

I use negated character classes to get the text between slashes in a generic way. This makes it easier to flag the later parts as optional using * for classes and ? for slashes (you can make the initial part less generic and just use /school/student/).

This would be easy using (PC)RE, however, Lua Patterns do not support optional capture groups as well as alternations. Instead, you can use PCRE patterns in Lua with the rex_pcre library or use the pattern-matching library Lpeg.

1 Comment

While It is a clever solution, it cannot distinguish between the exact /school/student/... and any other string with slashes, AFAIK. Not important if OP just works with /school/student/..., although.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.