Search code examples
regexluastring-matchinglua-patterns

Lua gmatch Regex Returning Nil


I am trying to select lines excluding the ones defined with keywords Cockos|VSTi|mono|x86|midi|MIDI|\\[vstcache\\]

Here is the Lua Regex pattern I am using, but getting a nil when I try to gmatch in Lua script '^(?:(?!Cockos|VSTi|mono|x86|midi|MIDI|\\[vstcache\\]).)*$\\r?\\n?'

  function GetPluginsTable()
        local context = ''
        local plugins_info = reaper.GetResourcePath()..'\\'..'reaper-vstplugins64.ini'
        f=io.open(plugins_info, 'r')
        if f then context = f:read('a') else return end
        f:close()  
        
          
          
        local tbl = {}
        local pattern = '^(?:(?!Cockos|VSTi|mono|x86|midi|MIDI|\\[vstcache\\]).)*$\\r?\\n?'        

        for line in context:gmatch(pattern) do tbl[#t+1] = line end
       
        return tbl
    end

local table = GetPluginsTable()
print(#table) -- I am getting nil pattern not matching???

Here is what I got in the reaper-vstplugins64.ini file that I am using the regular expressions on to selectively pick certain lines.

[vstcache]
reacast.dll=0088CADF36B2D801,1919246691,ReaCast (Cockos)
HoRNetTape_x64.vst3=000AF857F855D301,1773538056{F2AEE70D00DE4F4E48724E7454617065,HoRNetTape (HoRNet)
Kombinat_Tri.vst3=0041BA4D3D18D301,1880843185{5653544B6F6D336B6F6D62696E617420,Kombinat Tri (Audio Damage, Inc.) (mono)
Kontakt.vst3=0018E9A73448D801,821777587{5653544E6924446B6F6E74616B740000,Kontakt (Native Instruments) (64 out)!!!VSTi
GGain.dll=241679B662F2D601,1735999850,GGain (GVST)


I need the lines defined with keywords and also parse each line so the result in this case is

HoRNetTape
Kombinat Tri

These results are the name field after the second comma. when filtering out lines that has these keywords Cockos VSTi mono x86 midi MIDI vstcache


Solution

  • You are trying to use a Perl-compatible regular expression (PCRE) with string.gmatch, but string.gmatch accepts Lua patterns, not regular expressions.

    Lua patterns are less powerful than PCRE, and do not have an equivalent of constructions like (foo|bar|baz) which match one of a number of words. To work around this, you need to add logic to your application code that tests each word.

    This will probably look something like this:

    local excluded_plugin_patterns = {'Cockos', 'VSTi', 'mono', 'x86', 'midi', 'MIDI', '%[vstcache%]'}
    
    function GetPluginsTable()
        local context = ''
        local plugins_info = reaper.GetResourcePath() .. '\\' .. 'reaper-vstplugins64.ini'
    
        local plugins = {}
        f = io.open(plugins_info, 'r')
        if f then
            for line in f:lines() do
                local excluded = false
                for _, pattern in ipairs(excluded_plugin_patterns) do
                    if line:find(pattern) then
                        excluded = true
                        break
                    end
                end
                if not excluded then
                    -- Match everything left of the first period
                    local plugin = line:match("^(.-)%.")
                    if plugin then
                        table.insert(plugins, plugin)
                    end
                end
            end
        end
    
        return plugins
    end
    
    local plugins = GetPluginsTable()
    for _, plugin in ipairs(plugins) do
        print(plugin)
    end
    

    Note the %[vstcache%] pattern: Lua patterns use % to escape magic characters, not \ as used in PCRE.

    When parsing the plugin names from the INI file lines, this script tries to match anything left of the first period, and ignores any lines that don't contain a period. You may also wish to check for the first equals sign as well, in case any plugins in the INI file do not have an extension.