Алтернатива за съвпадение на шаблон за манипулиране на низове в Lua |

Има ли начин да направя модел на низ, който да съответства на "ab|cd", така че да съвпада или за "ab", или за "cd" във входния низ. Знам, че използвате нещо като "[ab]" като модел и ще съвпадне или за "a", или за "b", но това работи само за неща с една буква.

Имайте предвид, че действителният ми проблем е много по-сложен, но по същество просто трябва да знам дали има нещо ИЛИ в манипулирането на низове на Lua. Всъщност бих искал да сложа други модели от всяка страна на нещото ИЛИ и т.н. Но ако работи с нещо като "hello|world" и съвпада с "hello, world!" както с "hello", така и с "world", тогава е страхотно!


person user2704576    schedule 06.10.2013    source източник
comment
Не съм сигурен, че може лесно да се постигне с помощта на вградено съпоставяне на шаблони. Ако трябва да извършите сложен анализ/съпоставяне с помощта на Lua, можете да опитате lpeg: inf .puc-rio.br/~roberto/lpeg   -  person mpeterv    schedule 07.10.2013
comment
@peterm Да, това е доста лесно с lpeg! (lpeg.P("foo") + "bar"):match(input)   -  person dualed    schedule 07.10.2013


Отговори (3)


Използването на логически оператор с Lua модели може да реши повечето проблеми. Например за регулярния израз [hello|world]%d+ можете да използвате

string.match(str, "hello%d+") or string.match(str, "world%d+")

Веригата за бърз достъп на оператора or гарантира, че низът първо съвпада с hello%d+, ако не успее, тогава съвпада с world%d+

person Yu Hao    schedule 07.10.2013

За съжаление Lua шаблоните не са регулярни изрази и са по-малко мощни. По-специално те не поддържат редуване (онзи вертикален оператор | на Java или Perl регулярни изрази), което е, което искате да направите.

Едно просто решение може да бъде следното:

local function MatchAny( str, pattern_list )
    for _, pattern in ipairs( pattern_list ) do
        local w = string.match( str, pattern )
        if w then return w end
    end
end


s = "hello dolly!"
print( MatchAny( s, { "hello", "world", "%d+" } ) )

s = "cruel world!"
print( MatchAny( s, { "hello", "world", "%d+" } ) )

s = "hello world!"
print( MatchAny( s, { "hello", "world", "%d+" } ) )

s = "got 1000 bucks"
print( MatchAny( s, { "hello", "world", "%d+" } ) )

Изход:

hello
world
hello
1000

Функцията MatchAny ще съпостави първия си аргумент (низ) със списък от модели на Lua и ще върне резултата от първото успешно съвпадение.

person Lorenzo Donati -- Codidact.com    schedule 06.10.2013

Само за да разширим предложението на peterm, lpeg също предоставя re модул, който излага подобен интерфейс на стандартната string библиотека на lua, като същевременно запазва допълнителната мощност и гъвкавост, предлагани от lpeg.

Бих казал първо да изпробвате модула re, тъй като неговият синтаксис е малко по-малко езотеричен в сравнение с lpeg. Ето примерна употреба, която може да съответства на вашия пример за здравей свят:

dump = require 'pl.pretty'.dump
re = require 're'


local subj = "hello, world! padding world1 !hello hello hellonomatch nohello"
pat = re.compile [[
  toks  <-  tok (%W+ tok)*
  tok   <-  {'hello' / 'world'} !%w / %w+
]]

res = { re.match(subj, pat) }
dump(res)

което би извело:

{
  "hello",
  "world",
  "hello",
  "hello"
}

Ако се интересувате от улавяне на позицията на съвпаденията, просто променете леко граматиката за позиционно улавяне:

tok   <-  {}('hello' / 'world') !%w / %w+
person greatwolf    schedule 07.10.2013