![](/img/trans.png)
[英]How do I implement text streams, similar to cat in unix, in golang?
[英]How to implement regex /cat[s]?(\b|$)/ with ragel correclty?
我想加速我用 Go 編寫的程序,並使用ragel
將正則表達式轉換為有限狀態機。 在轉換類似於/cat[s]?(\\b|$)/
正則表達式時,我無法弄清楚如何正確匹配輸入的結尾(它匹配單詞邊框或輸入的結尾),所以我做了這個解決方法:
package main
import(
"strings"
"fmt"
"unicode"
)
func Match(data []byte) bool {
data = []byte(strings.ToLower(string(data)))
%%{
machine test;
write data;
}%%
cs, p, pe, eof := 0, 0, len(data), len(data)
_ = eof
var matchPos int
%%{
main := ('cat' 's'?) @{matchPos = p};
write init;
write exec;
}%%
return checkMatch(data, matchPos+1)
}
func checkMatch(data []byte, p int) bool {
if p == len(data) {
return true
}
tail := string(data[p:])
c := []rune(tail)[0]
if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
return true
}
return false
}
func main () {
vs := []string{
"cat",
"cats",
"cat and dog",
"cats and dogs",
"caterpillar",
}
for _, v := range vs {
fmt.Printf("'%s': %v\n", v, Match([]byte(v)))
}
}
輸出是正確的:
'cat': true
'cats': true
'cat and dog': true
'cats and dogs': true
'caterpillar': false
我確實認為有更好的方法。 用ragel
處理輸入結束的“正確”方法是什么?
當然,處理輸入結束的正確方法是使用 EOF 操作。 並使用一般的動作,像這樣(減少Match
功能):
var matched bool
%%{
action setMatched {
matched = true
}
main := ('cat' 's'?) %/setMatched ([ \t] >setMatched);
write init;
write exec;
}%%
// Variable generated and not used by Ragel.
_ = _test_trans_actions
return matched
這會產生以下輸出(注意添加了一個重要的測試用例):
'cat': true
'cats': true
'cat and dog': true
'cats and dogs': true
'catspaw': false
'caterpillar': false
它添加的是setMatched
操作,該操作由 EOF 在第一台機器( cats?
)的最終狀態之一( %/setMatched
)中觸發,或者在進入( >setMatched
)第二個狀態(幾乎是\\b
,但實際上可以用內部space
機代替)。 它完全消除了checkMatch
的需要。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.