func Test_Is_In_Strings(t *testing.T) { bs := []string{"abc", "bcd", "cde", "efg"} if !z.IsInStrings(bs, "bcd") { t.Error("bcd should be 1") } if z.IsInStrings(bs, "z123") { t.Error("z123 should be -1") } }
// 解析查询字符串 func (qb *QWBuilder) Parse(kwd string) *QWord { kwd = z.TrimExtraSpace(kwd) if len(kwd) == 0 { return nil } isGOr, isGAnd, flds, seps := qb.extractFldsAndSeps(kwd) // 解析为QWord qword := new(QWord) qword.CndMap = map[string]*QCnd{} sseps := len(seps) for i, fld := range flds { // qcnd qc := qb.evalQCnd(fld) if qc != nil { qword.Cnds = append(qword.Cnds, qc) qword.CndMap[qc.Key] = qc // 分隔符 if i < sseps { sp := "&" if isGOr { sp = "|" } else if isGAnd { sp = "&" } else if z.IsInStrings(qb.SepOr, string(seps[i])) { sp = "|" } else if z.IsInStrings(qb.SepAnd, string(seps[i])) { sp = "&" } qword.Rels = append(qword.Rels, sp) } } else { qword.Unmatchs = append(qword.Unmatchs, fld) } } return qword }
// 提取查询语句与连接符 func (qb *QWBuilder) extractFldsAndSeps(kwd string) (isGOr, isGAnd bool, flds []string, seps []byte) { // 判断全局参数 (先强制认为 'xxx:') // FIXME 后面改成正则匹配, 可以多加空格 isGOr = strings.HasPrefix(kwd, qb.GOr+":") isGAnd = strings.HasPrefix(kwd, qb.GAnd+":") if isGOr || isGAnd { kwd = kwd[strings.Index(kwd, ":")+1:] } // 分割查询字符串 flds = make([]string, 0, 5) seps = make([]byte, 0, 5) // FIXME 这个地方需要在好好想想 // 保证一个特殊情况下的正确性, 比如或是" "与是"," kwd中有类似"xxx , yyy"这样的语句,需要把处理 // 这个特例是一搬在" "当做或的情况下 if z.IsInStrings(qb.SepOr, " ") { for _, sAnd := range qb.SepAnd { ss := " " + sAnd + " " kwd = strings.Replace(kwd, ss, sAnd, -1) } } // 开始解析 kszie := len(kwd) fld := z.StringBuilder() for i := 0; i < kszie; i++ { c := kwd[i] z.DebugPrintf("extract kwd %3d -> [%s]\n", i, string(c)) // 如果是引用 if pos := z.IndexOfStrings(qb.QuoteBegin, string(c)); pos > 0 { // 这里面的空格啥的就不会被跳过了, 会一直取到引用结束, 逃逸字符会调整一下 for i++; i < kszie; i++ { c = kwd[i] if string(c) == qb.QuoteEnd[pos] { break } else if c == '\\' { // FIXME 这里没有做防守 i++ fld.Append(kwd[i]) } else { fld.Append(c) } } continue } // 如果是括弧 if z.IsInStrings(qb.BracketBegin, string(c)) { fld.Append(c) for i++; i < kszie; i++ { c = kwd[i] fld.Append(c) if z.IsInStrings(qb.BracketEnd, string(c)) { break } } continue } // 如果是分隔符 if z.IsInStrings(qb.SepAnd, string(c)) || z.IsInStrings(qb.SepOr, string(c)) { cfld := z.Trim(fld.String()) if len(cfld) > 0 { flds = append(flds, cfld) seps = append(seps, c) fld = z.StringBuilder() } continue } // 没什么特殊情况,那就加入到sb fld.Append(c) } // 加入最后一个条件 lfld := z.Trim(fld.String()) if len(lfld) > 0 { flds = append(flds, lfld) } // 打印一下 if z.IsDebugOn() && len(flds) > 0 { z.DebugPrintf("kwd : %s\n", kwd) for _, f := range flds { z.DebugPrintf("fld : %s\n", f) } for _, s := range seps { z.DebugPrintf("sep : '%s'\n", string(s)) } } return isGOr, isGAnd, flds, seps }