wzp
2021-06-08 85e2382799b60c823e3613256605fdde928b0fd6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AutoCheckSMS.Common;
 
namespace AutoCheckSMS
{
    /// <summary>
    /// 匹配模型
    /// </summary>
    public class Match
    {
        private static Match _instance;
        public static Match Instance {
            get {
                if (_instance == null)
                {
                    _instance = new Match();
                }
                return _instance;
            }
        }
 
 
 
        /// <summary>
        /// 正则匹配
        /// </summary>
        /// <returns></returns>
        public bool IsMatchByRegular(List<A_template> _Templates,string _Content)
        {
            List<A_template> list = _Templates.FindAll(c=>c.MatchType==1);//1表示正则匹配方式
            if (list.Count <= 0) return false;
 
            foreach (A_template template in list)
            {
                try
                {
                    Regex regex = new Regex(template.Template);
                    if (regex.IsMatch(_Content))
                    {
                        return true;
                    }
                }
                catch(Exception ex)
                {
                    Log4netService.Error($"异常:{ex.Message}");
                }
            }
            return false;
        }
 
 
        /// <summary>
        /// 通配符匹配
        /// </summary>
        /// <param name="_Templates"></param>
        /// <param name="_Content"></param>
        /// <returns></returns>
        public bool IsMatchByWildcard(List<A_template> _Templates, string _Content)
        {
            List<A_template> list = _Templates.FindAll(c => c.MatchType == 0);//1表示正则匹配方式
            if (list.Count <= 0) return false;
            foreach(A_template _Template in list)
            {
                try
                {
                    if (Greedy(_Content, _Template.Template))
                    {
                        return true;
                    }
                }
                catch (Exception ex)
                {
 
                    Log4netService.Error($"匹配异常:{ex.Message}");
                }
            }
 
 
            return false;
        }
 
        /// <summary>
        /// 贪心算法
        /// </summary>
        /// <param name="s">字符串</param>
        /// <param name="p">给定模式字符串</param>
        /// <returns></returns>
        private bool Greedy(string s, string p)
        {
            int sRight = s.Length, pRight = p.Length;
            //模式p的结尾不是*号,为?或字符,则与s的结尾一个个判断是否匹配
            while (sRight > 0 && pRight > 0 && p.Substring(pRight - 1,1) != "*")
            {
                if (CharMatch(s.Substring(sRight - 1,1), p.Substring(pRight - 1,1)))
                {
                    --sRight;
                    --pRight;
                }
                else
                {
                    //只要结尾有一个非*字符不能匹配s对应位置字符就返回false
                    return false;
                }
            }
            //p为空模式
            if (pRight == 0)
            {
                //s为空串则匹配,否则不匹配
                return sRight == 0;
            }
 
            int sIndex = 0, pIndex = 0;
            int sRecord = -1, pRecord = -1;
 
            while (sIndex < sRight && pIndex < pRight)
            {
                //出现 * 假设其不匹配任何字符,继续判断剩下的 s 和 p 是否匹配
                //并记录该 * 号下一个字符的下标,和对应的 s 的下标,便于(后悔)即不匹配的时候,返回来让 * 匹配部分 s 中的字符看剩下的是否匹配
                if (p.Substring(pIndex,1) == "*")
                {
                    ++pIndex;
                    sRecord = sIndex;
                    pRecord = pIndex;
                    //s[sIndex]和p[pIndex]匹配,则指针后移,判断剩下的是否匹配
                }
                else if (CharMatch(s.Substring(sIndex,1), p.Substring(pIndex,1)))
                {
                    ++sIndex;
                    ++pIndex;
                    // 出现了 * 号,且 * 不起作用时(即不匹配任何字符串时),s 和 p 不匹配则倒退回来(后悔),
                    // 让 * 代表部分 s 的字符串,继续判断剩下的是否匹配
                }
                else if (sRecord != -1 && sRecord + 1 < sRight)
                {
                    ++sRecord;
                    sIndex = sRecord;
                    pIndex = pRecord;
                }
                else
                {
                    return false;
                }
            }
 
            return AllStars(p, pIndex, pRight);
        }
 
        //判断;两个字符是否匹配
        private bool CharMatch(string u, string v)
        {
            return u == v || v == "?";
        }
 
        //若 p 的左边一部分已经完全匹配了 s ,则此时 pIndex < pRight, p 剩下的p(pIndex)到p(pRight) 部分必须全为*,才匹配
        //不然 s 不存在对应的字符串片段与 p 该段的字符相匹配,所以返回false
        //如果最后pIndex==pRight则返回true,是匹配的
        private bool AllStars(string str, int left, int right)
        {
            for (int i = left; i < right; ++i)
            {
                if (str.Substring(i,1) != "*")
                {
                    return false;
                }
            }
            return true;
        }
 
    }
}