fnmatch(pattern, str, FNM_NOESCAPE)
 
头文件:https://github.com/gcc-mirror/gcc/blob/master/include/fnmatch.h
源文件:https://github.com/gcc-mirror/gcc/blob/master/libiberty/fnmatch.c
 
源码解析,转自:https://www.cnblogs.com/oloroso/p/6861576.html

  1 /*
2 * Copyright (c) 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Guido van Rossum.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * From FreeBSD fnmatch.c 1.11
37 * $Id: fnmatch.c,v 1.3 1997/08/19 02:34:30 jdp Exp $
38 */
39
40 #ifndef _FNMATCH_H_
41 #define _FNMATCH_H_
42
43 #define FNM_NOMATCH 1 /* Match failed. */
44
45 #define FNM_NOESCAPE 0x01 /* 禁用反斜杠进行转义 */
46 #define FNM_PATHNAME 0x02 /* 斜杠只能被斜杠匹配(即不能被*或者?匹配) */
47 #define FNM_PERIOD 0x04 /* Period must be matched by period. */
48 /*如果这个标志设置了,string 里的起始点号必须匹配 pattern 里的点号。
49 一个点号被认为是起始点号,如果它是string 第一个字符,或者如果同时设
50 置了 FNM_PATHNAME,紧跟在斜杠后面的点号。
51 */
52 #define FNM_LEADING_DIR 0x08 /* Ignore /<tail> after Imatch. */
53 /*如果这个标志(GNU 扩展)设置了,模式必须匹配跟随在斜杠之后的 string
54 的初始片断。这个标志主要是给 glibc 内部使用并且只在一定条件下实现。
55 即只匹配目录路径部分,不匹配到具体文件名
56 */
57 #define FNM_CASEFOLD 0x10 /* 模式匹配忽略大小写. */
58 #define FNM_PREFIX_DIRS 0x20 /* Directory prefixes of pattern match too. */
59
60 /* Make this compile successfully with "gcc -traditional" */
61 #ifndef __STDC__
62 #define const /* empty */
63 #endif
64
65 int fnmatch(const char *, const char *, int);
66
67 #endif /* !_FNMATCH_H_ */
68
69 #if defined(LIBC_SCCS) && !defined(lint)
70 static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
71 #endif /* LIBC_SCCS and not lint */
72
73 /*
74 * 函数fnmatch(),如POSIX 1003.2-1992 B.6节所述。
75 * 将文件名或者目录名与pattern进行比较
76 */
77
78 #include <ctype.h>
79 #include <string.h>
80 #include <stdio.h>
81
82 // 定义字符串结尾标志
83 #define EOS '\0'
84
85 static const char *rangematch(const char *, char, int);
86
87 int
88 fnmatch(const char *pattern, const char *string, int flags)
89 {
90 const char *stringstart;
91 char c, test;
92
93 for (stringstart = string;;){
94 // 逐个取匹配字符串中的成分(分为*?和range三种)
95 switch (c = *pattern++) {
96 case EOS: // 没有匹配串的情况
97 // 如果忽略'/'后面的部分,则匹配成功
98 if ((flags & FNM_LEADING_DIR) && *string == '/'){
99 return (0);
100 }
101 // 如果string也是空串,则匹配成功
102 return (*string == EOS ? 0 : FNM_NOMATCH);
103 case '?': // 匹配单个任意字符
104 // string为空则不能匹配
105 if (*string == EOS){
106 return (FNM_NOMATCH);
107 }
108 // 判断'/'是否只能由'/'进行匹配
109 if (*string == '/' && (flags & FNM_PATHNAME)){
110 return (FNM_NOMATCH);
111 }
112 // 判断是否string中的起始'.'必须匹配pattern中的'.'(即'?'不能匹配'.')
113 if (*string == '.' && (flags & FNM_PERIOD) &&
114 (string == stringstart ||
115 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))){
116 return (FNM_NOMATCH);
117 }
118 // 匹配成功则匹配string的下一个字符
119 ++string;
120 break;
121 case '*': // 匹配单个或多个任意字符
122 c = *pattern;
123 /* 多个'*'当做一个 */
124 while (c == '*'){
125 c = *++pattern;
126 }
127 // 判断是否需要对'.'进行处理
128 if (*string == '.' && (flags & FNM_PERIOD) &&
129 (string == stringstart ||
130 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))){
131 return (FNM_NOMATCH);
132 }
133
134 /* 优化 * 在匹配串结尾或者在 /. 之前的匹配*/
135 if (c == EOS){ // 在结尾
136 // 判断 * 是否不匹配斜杠
137 if (flags & FNM_PATHNAME){
138 // 不匹配斜杠,则判断是否忽略'/'之后部分
139 return ((flags & FNM_LEADING_DIR) ||
140 ((strchr(string, '/') == NULL) ? 0 : FNM_NOMATCH));
141 }else{
142 return (0);
143 }
144 }
145 else if (c == '/' && flags & FNM_PATHNAME) { // 在 /. 之前
146 // 如果string后没有 '/'则匹配失败
147 if ((string = strchr(string, '/')) == NULL){
148 return (FNM_NOMATCH);
149 }
150 break;
151 }
152
153 /* 非特殊情况下,递归匹配 */
154 while ((test = *string) != EOS) {
155 // 不对'.'进行特殊处理,进行匹配(则只需判断'/'匹配情况)
156 if (!fnmatch(pattern, string, flags & ~FNM_PERIOD)){
157 return (0); // 匹配成功
158 }
159 // 对 '/'进行处理(斜杠只匹配斜杠,则匹配失败)
160 if (test == '/' && flags & FNM_PATHNAME){
161 break;
162 }
163 ++string;
164 }
165 // 返回匹配失败(即*没有匹配成功,'.'和'/'上的匹配没有成功)
166 return (FNM_NOMATCH);
167 case '[': // range 范围匹配
168 if (*string == EOS){
169 return (FNM_NOMATCH); // 空串匹配失败
170 }
171 if (*string == '/' && flags & FNM_PATHNAME){
172 return (FNM_NOMATCH); // '/'匹配失败
173 }
174 if ((pattern =
175 rangematch(pattern, *string, flags)) == NULL){
176 return (FNM_NOMATCH); // 范围匹配失败
177 }
178 ++string;
179 break;
180 case '\\': // 斜杠匹配(判断是否需要转义)
181 if (!(flags & FNM_NOESCAPE)) {
182 if ((c = *pattern++) == EOS) {
183 c = '\\';
184 --pattern;
185 }
186 }
187 /* 非上述部分,则直接匹配单个字符 */
188 default:
189 if (c == *string){
190 ; // 直接匹配上了
191 }else if ((flags & FNM_CASEFOLD) &&
192 (tolower((unsigned char)c) ==
193 tolower((unsigned char)*string))){
194 ; // 忽略大小写匹配成功
195 }
196 else if ((flags & FNM_PREFIX_DIRS) && *string == EOS &&
197 ((c == '/' && string != stringstart) ||
198 (string == stringstart + 1 && *stringstart == '/'))){
199 return (0); // 匹配成功
200 }
201 else{
202 return (FNM_NOMATCH); // 匹配失败
203 }
204 string++;
205 break;
206 }
207 }
208 /* NOTREACHED */
209 }
210
211 // 字符范围匹配
212 // pattern传入如 [a-x]*** 形式的字符串
213 // 匹配失败或匹配到EOS结束(也是失败),返回NULL
214 // 成功返回匹配串的下一个匹配成分首地址
215 static const char *
216 rangematch(const char *pattern, char test, int flags)
217 {
218 // 此处没有对c进行初始化,可能出问题(栈上变量默认值未定)
219 int negate, ok;
220 char c, c2;
221
222 /*
223 * A bracket expression starting with an unquoted circumflex
224 * character produces unspecified results
225 * 以无引号 ^ 字符开始的方括号表达式,将产生未指定的结果
226 * (IEEE 1003.2-1992,3.13.2). 此实现将其视为 '!',以与正则表达式语法保持一致.
227 * J.T. Conklin (conklin@ngai.kaleida.com)
228 */
229 // 检测方括号表达式中第一个字符
230 // 如果为!或者^,则对后面匹配的结果取反
231 if ((negate = (*pattern == '!' || *pattern == '^'))){
232 ++pattern;
233 }
234
235 // 忽略大小写,则转为小写处理
236 if (flags & FNM_CASEFOLD){
237 test = tolower((unsigned char)test);
238 }
239 // 循环到方括号表达式结束
240 for (ok = 0; (c = *pattern++) != ']';) {
241 // 如果没有禁用转义,获取字符
242 if (c == '\\' && !(flags & FNM_NOESCAPE)){
243 c = *pattern++;
244 }
245 // 匹配结束
246 if (c == EOS){
247 return (NULL);
248 }
249 // 忽略大小写,则转为小写
250 if (flags & FNM_CASEFOLD){
251 c = tolower((unsigned char)c);
252 }
253 // 如果当前匹配项c 的下一个是'-',则获取'-'后面的一个字符
254 // 例如,匹配串为 [a-x] 当前c为a,则c2为x,表示匹配a-x之间字符
255 if (*pattern == '-'
256 && (c2 = *(pattern + 1)) != EOS && c2 != ']') {
257 pattern += 2;
258 // 判断是否需要转义
259 if (c2 == '\\' && !(flags & FNM_NOESCAPE)){
260 c2 = *pattern++;
261 }
262 if (c2 == EOS){
263 return (NULL);
264 }
265 // 判断是否区分大小写
266 if (flags & FNM_CASEFOLD){
267 c2 = tolower((unsigned char)c2);
268 }
269 // 判断test是否位于 [c,c2]区间
270 if ((unsigned char)c <= (unsigned char)test &&
271 (unsigned char)test <= (unsigned char)c2){
272 ok = 1;
273 }
274 }
275 else if (c == test){
276 ok = 1;
277 }
278 }
279 // 返回匹配结果
280 return (ok == negate ? NULL : pattern);
281 }

c、c++字符串匹配的更多相关文章

  1. 字符串匹配的KMP算法

    ~~~摘录 来源:阮一峰~~~ 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串”BBC ABCDAB ABCDABCDABDE”,我想知道,里面是否包含另一个字符串”ABCDABD”? 许 ...

  2. {Reship}{KMP字符串匹配}

    关于KMP字符串匹配的介绍和归纳,作者的思路非常清晰,推荐看一下 http://blog.csdn.net/v_july_v/article/details/7041827

  3. 字符串匹配(hash算法)

    hash函数对大家来说不陌生吧 ? 而这次我们就用hash函数来实现字符串匹配. 首先我们会想一下二进制数. 对于任意一个二进制数,我们将它化为10进制的数的方法如下(以二进制数1101101为例): ...

  4. 【C++实现python字符串函数库】二:字符串匹配函数startswith与endswith

    [C++实现python字符串函数库]字符串匹配函数startswith与endswith 这两个函数用于匹配字符串的开头或末尾,判断是否包含另一个字符串,它们返回bool值.startswith() ...

  5. sdut 2125串结构练习--字符串匹配【两种KMP算法】

    串结构练习——字符串匹配 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目链接:http://acm.sdut.edu.cn/sduto ...

  6. C语言字符串匹配函数

    C语言字符串匹配函数,保存有需要时可以用: #include <stdio.h> #include <stdlib.h> #include <string.h> # ...

  7. 字符串匹配--Karp-Rabin算法

    主要特征 1.使用hash函数 2.预处理阶段时间复杂度O(m),常量空间 3.查找阶段时间复杂度O(mn) 4.期望运行时间:O(n+m) 本文地址:http://www.cnblogs.com/a ...

  8. 字符串匹配的KMP算法详解及C#实现

    字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...

  9. zstu.4194: 字符串匹配(kmp入门题&& 心得)

    4194: 字符串匹配 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 206  Solved: 78 Description 给你两个字符串A,B,请 ...

  10. 字符串匹配与KMP算法实现

    >>字符串匹配问题 字符串匹配问题即在匹配串中寻找模式串是否出现, 首先想到的是使用暴力破解,也就是Brute Force(BF或蛮力搜索) 算法,将匹配串和模式串左对齐,然后从左向右一个 ...

随机推荐

  1. tomcat报错:java.io.IOException: No space left on device

    1 简介 今天网站很多页面访问突然就404了,路径分明没有变,是正确的,就很奇怪 排查日志发现报错java.io.IOException: No space left on device 这个错误,是 ...

  2. MRS+LakeFormation:打造一站式湖仓,释放数据价值

    摘要:华为LakeFormation是企业级的一站式湖仓构建服务. 本文分享自华为云社区<华为云MRS支持LakeFormation能力,打造一站式湖仓,释放数据价值]>,作者:break ...

  3. Svelte框架结合SpreadJS实现表格协同文档

    SpreadJS是葡萄城结合 40 余年专业控件技术和在电子表格应用领域的经验而推出的纯前端表格控件.作为一个类Excel控件,SpreadJS如何实现当前比较流行的表格协同呢?本篇文章将简单介绍一下 ...

  4. vue+elementUI 实现设置还款日字母弹窗组件

    1.业务背景 还款业务,设置每月还款日,选每月几号扣款,不需要29.30.31,因为不是每个月都有这三天的 2.预期效果图 3.代码实现 3.1 初始化vue项目 地址:https://cn.vuej ...

  5. SpringCloud GateWay网关(入门)

    1.介绍 强烈推荐,看官网文档 Spring Cloud Gateway ①简介 Cloud全家桶里有个重要组件:网关 SpringCloud Gateway基于WebFlux框架 WebFlux底层 ...

  6. ft5426触摸屏I2C

    触摸的点数, 先写入地址0x38, 寄存器0x02, 再次读取0x38的数据,得到1个触摸点 读取全部坐标信息,需要读入30字节数据

  7. DVWA靶场实战(十四)——JavaScript

    DVWA靶场实战(十四) 五.Java Script: 1.漏洞原理: 这里的JavaScript其实是JavaScript Attack也就是JS攻击.JavaScript是一种基于对象和事件驱动的 ...

  8. react 高效高质量搭建后台系统 系列 —— 结尾

    其他章节请看: react 高效高质量搭建后台系统 系列 尾篇 本篇主要介绍表单查询.表单验证.通知(WebSocket).自动构建.最后附上 myspug 项目源码. 项目最终效果: 表单查询 需求 ...

  9. JAVASE小练习 (今天做一个基于javase的银行ATM小练习)

    实现的功能有1,用户登录2,用户开户(基于用户登录)3,查询账户(基于用户登录)4,存款5,取款6,转账7,修改密码(只有三次确认密码的机会)8,退出登录9,注销 这个小例子可以让我们充分复习所学的j ...

  10. Gear_Of_War#1

    Gear_Of_War#1 目录 Gear_Of_War#1 1 信息收集 1.1 端口扫描 1.2 后台目录扫描 1.3 SMB服务安全分析 2 GetShell 2.1 ssh登录marcus用户 ...