2016-10-22 54 views
3

我試圖寫一個LPEG模式來匹配字符串其中:LPEG模式相匹配的字符串不連續hypens

  • 以字母開頭
  • 後包含字母數字字符
  • 不含有兩個或多個連續的連字符(例如不允許test--string

僅供參考,正則表達式匹配[a-zA-Z](-?[a-zA-Z0-9])*什麼我要找的。

這裏是我的工作的代碼,以供參考:

require "lpeg" 
P,R,C = lpeg.P,lpeg.R,lpeg.C 

dash = P"-" 
ucase = R"AZ" 
lcase = R"az" 
digit = R"09" 
letter = ucase + lcase 
alphanum = letter + digit 

str_match = C(letter * ((dash^-1) * alphanum)^0) 

strs = { 
    "1too", 
    "too0", 
    "t-t-t", 
    "t-t--t", 
    "t--t-t", 
    "t-1-t", 
    "t--t", 
    "t-one1", 
    "1-1", 
    "t-1", 
    "t", 
    "tt", 
    "t1", 
    "1", 
} 

for _,v in ipairs(strs) do 
    if lpeg.match(str_match,v) ~= nil then 
     print(v," => match!") 
    else 
     print(v," => no match") 
    end 
end 

然而,令我沮喪,我得到下面的輸出:

1too  => no match 
too0  => match! 
t-t-t => match! 
t-t--t => match! 
t--t-t => match! 
t-1-t => match! 
t--t  => match! 
t-one1 => match! 
1-1  => no match 
t-1  => match! 
t  => match! 
tt  => match! 
t1  => match! 
1  => no match 

儘管什麼碼輸出,t-t--tt--t-tt--t不應該匹配。

+1

採取在'((破折號仔細看看^ -1) * alphanum)^ 0'!你說「把最多一個破折號後跟一個字母數字的可能性分組,這一切都可能發生0次或更多次。」所以你的模式可能會在開頭的字母上失敗。 – Youka

回答

2

在您的模式letter * ((dash^-1) * alphanum)^0中,lpeg會嘗試匹配字符串的前綴。對於您沒想到比賽的情況下

TT --t
牛逼 --tt
牛逼 --t

的部分用粗體突出顯示是你的模式成功匹配的地方。 lpeg.match返回最後的位置(這是一個數字),如果沒有捕獲到任何東西,它可以解析使用你的模式。對於上述3種情況,捕獲的匹配子部分將解釋您所看到的錯誤輸出。

如果您只是每次匹配一個字符串,則可以修改模式以檢查解析後是否還有剩餘的字符。

str_match = C(letter * ((dash^-1) * alphanum)^0) * -1 

類似地使用lpeg.re模塊

re_pat = re.compile "{ %a ('-'? %w)* } !." 

對於流匹配或發現在目標串中的所有圖案出現,可堆疊的語法規則共同這樣

stream_parse = re.compile 
[[ 
    stream_match <- ((str_match/skip_nonmatch) delim)* str_match? 
    str_match  <- { %a ('-'? %w)* } (&delim/!.) 
    skip_nonmatch <- !str_match (!delim .)* 

    delim   <- %s+ 
]] 

任何匹配將得到捕獲並返回。如果沒有匹配,您將返回nil或指示模式停止解析的字符串中的哪個位置。

編輯:對於您所需要的解析就沒有匹配返回nil案件,這個調整的語法應該做的伎倆

stream_parse = re.compile 
[[ 
    stream_match <- (str_match/skip_nonmatch+ &str_match)+ 
    str_match  <- { %a ('-'? %w)* } (&delim/!.) 
    skip_nonmatch <- !str_match (!delim .)* delim 

    delim   <- %s+ 
]]