package pretreated import ( "regexp" "sort" "strings" ) var ( /** 监理 施工没有处理 **/ //替换容易混淆的词 PreReg = regexp.MustCompile("(同|每|对|[^其]中|仅|任意)[一二三四五六七八九十\\d]个?(子|合同|分|施工|监理)?(标段?|包)|项目标号|文件A包|涉及包号|包件号|0\\s?个标段|1\\-[\\d]标段|子包(\\d、)+\\d|\\d\\.\\d(标段|包)[^一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]|[1-9]标。") PreReg1 = regexp.MustCompile("[^\n]([A-Z]?([一二三四五六七八九十]|\\d)、)+[A-Z]?([一二三四五六七八九十]|\\d)(标段?|包)") //有分包划分情况的直接对比是1的肯定不是分包 PreCheckMulti = regexp.MustCompile("[^第]([一二三四五六七八九十两0-9ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]+)[  \u3000\u2003\u00a0]*个?((子|合同|分|施工|监理)?(标段?|包|合同段|标包))进行([一二三四五六七八九十两0-9ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]+)|(划分|分[设为成]?|共[分设有计]?)[::]?[  \u3000\u2003\u00a0]*([一二三四五六七八九十两0-9ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]+)[  \u3000\u2003\u00a0]*个?((子|合同|分|施工|监理)?(标段?|包|合同段|标包|项目))") //替换容易混淆的词 PreCon = regexp.MustCompile("([\r\n]|^)[\u3000\u2003\u00a0\\s]*(^标项)(\\d\\.)+\\d|[一二三四五1-9、.]+[  \u3000\u2003\u00a0]*((标段|分包)(划分|情况)|(标书))|([上下]一[条页篇][::]?[^,,。\\n]{0,120}|备注[::][^\\n]{0,120}|业绩[::][^\\n,。,]{0,80}|三包(手册|服务|政策|凭证|期|标准|规定|责任|要求|售后)|(要求|提供|质量|国家|享受|负责|实行|执行|承诺|门前|法定|规定).{0,6}三包|“三包”|\\d+万?([个套只支分名][^标包])|[?]|[((]请?注意[::][^((]+[))])") PreCon2 = regexp.MustCompile("[评中开定]\\s?标\\s?[0-9一二三四五六七八九十]+|标[准尺高书注]|[^中]标价|[开鼠投招军指企目]标|包[括含装为内]|[承树]包|CA证书|地点[::].*标|.{30,}合同段") PreCon3 = regexp.MustCompile("(标段[一二三四五六七八九十0-9A-Za-z])[((].*[))][::]") PreCon5 = regexp.MustCompile("^(标一)(包[一二三四五六七八九十0-9A-Za-z]+)$") //提取分包标识 MultiReg = regexp.MustCompile("(([一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ\\-])+(包|标段|分标))[::]?|(?:^|\\n)([一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ\\-]+(包))|([第]?([一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ\\-]+)#?((子|合同|分|施工|监理)?(标段?|合同段|标包)))|(((子|合同|施工|监理|标包|标|包)(标|包段|项|段|组)?)[     ]*([一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ\\-]+))|((项目|包件)([一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]+))|((包组|包件)[::\\s]+([一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ\\-]+))|((施工|监理)(标段))[::\n]") PreCon4 = regexp.MustCompile("([一二三四五六七八九十]标段[::¥0-9.]*(万元)?)[、]?") Precon4dw = regexp.MustCompile("(万元|元)") //匹配到的包格式分类统计 keyregs = []map[*regexp.Regexp]int{ map[*regexp.Regexp]int{ regexp.MustCompile("^[一二三四五六七八九十]+$"): 8, }, map[*regexp.Regexp]int{ regexp.MustCompile("^[0-9]+$"): 7, }, map[*regexp.Regexp]int{ regexp.MustCompile("^[A-Za-z]+[0-9]*$"): 6, }, } //冒号处理优先级高 如标段一: MH = regexp.MustCompile("[::]") //匹配包有的时候类似 包2LN2的只保留前面数字 ignoreReg = regexp.MustCompile("^(\\d+)[A-Za-z].*") //标题中含分包特征的标段一、二、三或包1、包2之类,根据 TitleReg = regexp.MustCompile("([一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ、\\-~至]+(子|合同|分|施工|监理|标)?[包标段][号段]?[、]?)+|((子|合同|分|施工|监理|标)?[包标段][号段]?[一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ、\\-~至]+[、]?)+|(子|合同|分|施工|监理|标)?[包标段][号段]?[a-zA-Z0-9]+[\\-~-至、](子|合同|分|施工|监理|标)?[包标段][号段]?[a-zA-Z0-9]+") clearPkgFlag = regexp.MustCompile("^[\\-]+|[\\-]+$") //无效冗余包名 cleanPkgName = regexp.MustCompile("^(1[-][23456789]包|一[-][二三四五六七八九]包|(施工|监理)BIM)$") cleanPkgCon = regexp.MustCompile("(不足三家.*包采购.*终止)") ) //判断分包 func CheckMultiPackage(con string) (content string, m map[string][]string, b bool) { m = map[string][]string{} con = PreReg.ReplaceAllString(con, "") con = PreReg1.ReplaceAllString(con, "") content = con con = PreCheckMulti.ReplaceAllString(con, "") con = PreCon.ReplaceAllString(con, "\n") con = PreCon2.ReplaceAllString(con, "") con = PreCon3.ReplaceAllString(con, "${1}:") //替换敏感词-分割 con = replaceSenstiveReg1.ReplaceAllString(con, "${1}\n${2}") //修改 \nX标段 res := MultiReg.FindAllStringSubmatch(con, -1) if len(res) > 0 { //1-3 45 6-10 11-15 16-18 19-21 22-24 mindex := map[string]int{} for index, v := range res { k := v[1] vindex := 2 if k == "" { k = v[4] vindex = 5 } if k == "" { k = v[6] vindex = 7 } if k == "" { k = v[11] vindex = 12 } if k == "" { k = v[16] vindex = 17 } if k == "" { k = v[19] vindex = 20 } if k == "" { k = v[22] vindex = 23 } if k != "" && v[vindex] != "" && vindex != 5 { vindex += 1 } if len(m[k]) == 0 && k != "" && v[vindex] != "" { k = ignoreReg.ReplaceAllString(k, "$1") k = clearPkgFlag.ReplaceAllString(k, "") m[k] = []string{clearPkgFlag.ReplaceAllString(strings.TrimSpace(v[0]), ""), v[vindex]} mindex[k] = index } } //过滤无效包 new_m := map[string][]string{} for k, v := range m { if cleanPkgName.MatchString(k) { continue } new_m[k] = v } m = new_m if len(m) > 1 { //对k优先级进行处理过滤 SEL := -1 //确定以哪种类型为标段标识,没有去判断v相同不相同,存在一定的误判!如 1:合同包1 1:包 mapclassstr := map[int]map[string][]string{} mapclass := map[int]int{} for k, v := range m { str := res[mindex[k]][0] mk := 5 for _, keyreg := range keyregs { for reg, pos := range keyreg { if reg.MatchString(k) { mk = pos break } } } mapclass[mk]++ if mapclassstr[mk] == nil { mapclassstr[mk] = map[string][]string{} } mapclassstr[mk][k] = []string{v[0], v[1]} if MH.MatchString(str) { //如果有冒号直接确定 SEL = mk } } //log.Println(mapclassstr, mapclass, SEL) if SEL > 0 { m = mapclassstr[SEL] } else { //比较出哪个最多,倒排,如果都一样,按 9 8 7 6 5来处理 max := 0 maxk := []int{} for k, v := range mapclass { if v > max { max = v maxk = []int{} maxk = append(maxk, k) } else if v == max { maxk = append(maxk, k) } } if len(maxk) > 0 { sort.Ints(maxk) m = mapclassstr[maxk[len(maxk)-1]] } } } if len(m) > 0 { b = true } //log.Println(m, res) } return }