2
votes

I'm writting a command line parser for Lua and I would like to extract options' names and their values using Lua string.match().

A command line option is defined as : --name=value

Here is the code I use (can be found here) :

local expr = '--username=John'
local name, value = expr:match( '^%-%-(.*)=%"?(.*)%"?' )
print( "found values for '" .. expr .. "'" )
print( name .. " = " .. value )

the ouput is OK :

found values for '--username=John'
username = John

but if I want to set a value with spaces I enclose it between double-quotes

local expr = '--username="John Doe"'
local name, value = expr:match( '^%-%-(.*)=%"?(.*)%"?' )
print( "found values for '" .. expr .. "'" )
print( name .. " = " .. **value )

The output is not what I want since the last double-quote has been extracted by string.match()

found values for '--username="John Doe"'
username = John Doe"

Is my pattern wrong or is it a Lua bug ?

1

1 Answers

0
votes

There is no bug, your pattern contains a greedy .* pattern that matches as many occurrences of any char as possible. It grabs the whole string, and then backtracks to see if there are any other obligatory subpatterns to yield text to. Since "? can match an empty string, it matches it after " and " turns out in the capture.

There are several ways out. Here are two:

name, value = expr:match( '^%-%-(.*)="?([^"]*)"?' )

or

name, value = expr:match( '^%-%-(.*)="?(.-)"?$' )

See the online demo printing

found values for '--username="John Doe"'
username = John Doe

Details

  • The first approach is using a negated character class, ([^"]*). It matches any 0+ chars other than ". So, it cannot match the last "
  • The second one is using (.-)"?$, a lazy .- (that matches 0+ chars as few as possible, up to but not including a " (if present) that is at the end of the string ($).