3_05_GLib库入门与实践_Glob_Pattern模式匹配

简介

Glob风格模式匹配,即使用特定的字符(被称为元字符),实现快速匹配字符串的目的。与正则表达式相比,glob风格通配符更加简单,速度也更快,但功能相对来说没有正则表达式那么强大。
Glob风格模式匹配应用场景举例:

  • 在shell命令行,我们经常会输入ls ./dir/*,这就是一个glob风格的通配符。
  • 在git中,.gitignore文件,是glob风格模式匹配。
  • 在redis数据库订阅、发布功能中也用到了glob风格模式匹配。

不同语言提供的Glob库支持规则也不相同,这里列举常见的Glob风格模式规则和说明。

通配符描述
*匹配任意长度字符
?匹配一个字符
\匹配转义符 \
[a-z]匹配大于等于a,小于等于z;适用任何字符
[0123456789]匹配大于等于0,小于等于9;相当于[0-9]
[^]非,匹配不相等字符
[^a-z]不匹配大于等于a,小于等于z;适用任何字符
[\]匹配转义符

注:GLib的Glob规则只支持*?,其他的都不支持。

数据结构

将模式字符串编译为spec形式。本结构体是一个不透明类型数据结构,我们可以整体使用它,但无法单独引用其内部的一个结构体成员。

typedef struct _GPatternSpec GPatternSpec;

函数列表

GPatternSpec * 	g_pattern_spec_new ()
void 	g_pattern_spec_free ()
gboolean 	g_pattern_spec_equal ()
gboolean 	g_pattern_match ()
gboolean 	g_pattern_match_string ()
gboolean 	g_pattern_match_simple ()

函数功能分类

// 模式串创建
GPatternSpec * 	g_pattern_spec_new ()

// 模式串释放
void 	g_pattern_spec_free ()

// 比较两个模式串是否相同
gboolean 	g_pattern_spec_equal ()

// 匹配函数
//  当需要多次匹配或者模式串复杂时,可以调用本函数,需要传入字符串的逆序字符串。
gboolean 	g_pattern_match ()  
// 和g_pattern_match相似,但不需要传入一个逆序字符串,当匹配逻辑不复杂时,可以使用本函数,或者当模式串固定,但待匹配字符串不固定时,这样使用效率高。
gboolean 	g_pattern_match_string ()  
// 最简单的模式匹配函数,传入一个模式规则串和一个正常字符串,即返回是否匹配
gboolean 	g_pattern_match_simple ()  

函数功能说明及综合演示

星号通配符演示

星号通配符(*)表示匹配任意长度的字符串,下面是演示程序。
源码见glib_examples\glib_glob\glib_glob_asterisk_mark

#include <glib.h>
static void _inner_glob_asterisk(const char *pattern, const char *string)
{
    GPatternSpec *pspec = NULL;
    gboolean r = FALSE;
    if( (NULL == pattern) || (NULL == string) ) {
        g_print("input param is NULL \n");
        return;
    }
    pspec = g_pattern_spec_new(pattern);
    r = g_pattern_match_string(pspec, string);
    g_print("%s %s match %s \n", pattern, r?"is":"not", string);
    g_pattern_spec_free(pspec);
    return;
}
static void test_glob_asterisk(void)
{
    _inner_glob_asterisk("a*", "abcd");
    _inner_glob_asterisk("ab*", "abcd");
    _inner_glob_asterisk("ac*", "abcd");
    _inner_glob_asterisk("*b*", "abcd");
    _inner_glob_asterisk("abc*", "abcd");
    _inner_glob_asterisk("ab*d", "abcd");
    _inner_glob_asterisk("abcd*", "abcd");
    return;
}
gint main(gint argc, gchar **argv)
{
    g_test_init(&argc, &argv, NULL);
    g_test_add_func ("/glob/asterisk", test_glob_asterisk);
    return g_test_run();
}

运行结果:

[root@centos7 build]# ./glib_glob_asterisk_mark
/glob/asterisk: a* is match abcd
ab* is match abcd
ac* not match abcd
*b* is match abcd
abc* is match abcd
ab*d is match abcd
abcd* is match abcd
OK
问号通配符演示

问号通配符(?)只匹配一个字符,下面是演示程序。
源码见glib_examples\glib_glob\glib_glob_question_mark

#include <glib.h>
static void _inner_glob_question(const char *pattern, const char *string)
{
    GPatternSpec *pspec = NULL;
    gboolean r = FALSE;
    if( (NULL == pattern) || (NULL == string) ) {
        g_print("input param is NULL \n");
        return;
    }
    pspec = g_pattern_spec_new(pattern);
    r = g_pattern_match_string(pspec, string);
    g_print("%s %s match %s \n", pattern, r?"is":"not", string);
    g_pattern_spec_free(pspec);
    return;
}
static void test_glob_question(void)
{
    _inner_glob_question("a?cd", "abc");
    _inner_glob_question("a?b", "abc");
    _inner_glob_question("a?c", "abc");
    _inner_glob_question("a?d", "abd");
    _inner_glob_question("a?d", "acd");
    _inner_glob_question("a??d", "abcd");
    _inner_glob_question("a??d", "abdd");
    _inner_glob_question("a??d", "wxyz");
    return;
}
gint main(gint argc, gchar **argv)
{
    g_test_init(&argc, &argv, NULL);
    g_test_add_func ("/glob/question", test_glob_question);
    return g_test_run();
}

运行结果:

[root@centos7 build]# ./glib_glob_question_mark
/glob/question: a?cd not match abc
a?b not match abc
a?c is match abc
a?d is match abd
a?d* is match acd
a??d is match abcd
a??d is match abdd
a??d not match wxyz
OK
方括号模式匹配演示(不支持,会被视作普通字符串)

GLib不支持方括号([ ])模式匹配语法,会将方括号视作普通字符串。下面演示说明。
源码见glib_examples\glib_glob\glib_glob_brackets_mark

#include <glib.h>
static void _inner_glob_brackets(const char *pattern, const char *string)
{
    GPatternSpec *pspec = NULL;
    gboolean r = FALSE;
    if( (NULL == pattern) || (NULL == string) ) {
        g_print("input param is NULL \n");
        return;
    }
    pspec = g_pattern_spec_new(pattern);
    r = g_pattern_match_string(pspec, string);
    g_print("%s %s match %s \n", pattern, r?"is":"not", string);
    g_pattern_spec_free(pspec);
    return;
}
static void test_glob_brackets(void)
{
    _inner_glob_brackets("[Aa]bc", "abc");
    _inner_glob_brackets("[Aa]bc", "Abc");
    _inner_glob_brackets("[Aa]bc", "Aabc");
    _inner_glob_brackets("[Aa]bc", "[Aa]bc");
 
    return;
}
gint main(gint argc, gchar **argv)
{
    g_test_init(&argc, &argv, NULL);
    g_test_add_func ("/glob/brackets", test_glob_brackets);
    return g_test_run();
}

运行结果:

[root@centos7 build]# ./glib_glob_brackets_mark
/glob/brackets: [Aa]bc not match abc
[Aa]bc not match Abc
[Aa]bc not match Aabc
[Aa]bc is match [Aa]bc
OK
三种匹配函数演示

GLib Glob模式匹配提供了三种match函数,其中最简单的是g_pattern_match_simple,直接将一个模式串和一个待匹配字符串传入本函数,不需要对模式串预先编译,使用非常方便,当需要多次匹配时,将模式串预编译,可以提高效率,g_pattern_match_string或g_pattern_match函数都需要预编译模式串,g_pattern_match_string适合于比较简单的模式匹配,当模式串复杂时,最好使用g_pattern_match,该函数要求传入待匹配字符串的逆序字符串,可以加快匹配速度,注意字符串逆序的时候,需要使用g_utf8_strreverse函数,因为字符串可能是非单字节的。
源码见glib_examples\glib_glob\glib_glob_match

#include <glib.h>

static void test_glob_match_simple(void)
{
    gboolean r = FALSE;

    r = g_pattern_match_simple("a?c", "abc");
    g_print("a?c %s match abc \n", r?"is":"not");

    return;
}

static void test_glob_match_string(void)
{
    GPatternSpec *pspec = NULL;
    gboolean r = FALSE;

    const gchar *pattern = "a?c*";
    const gchar *string = "abcdef";

    pspec = g_pattern_spec_new(pattern);

    r = g_pattern_match_string(pspec, string);
    g_print("%s %s match %s \n", pattern, r?"is":"not", string);

    g_pattern_spec_free(pspec);

    return;
}

static void test_glob_match_match(void)
{
    GPatternSpec *pspec = NULL;
    gboolean r = FALSE;

    const gchar *pattern = "hello你好*";
    const gchar *string = "hello你好啊hello";
    gchar *str_r = NULL;

    pspec = g_pattern_spec_new(pattern);

    str_r = g_utf8_strreverse (string, -1);
    r = g_pattern_match(pspec, strlen(string), string, str_r);
    g_print("%s %s match %s \n", pattern, r?"is":"not", string);

    g_free(str_r);
    g_pattern_spec_free(pspec);

    return;
}

gint main(gint argc, gchar **argv)
{
    g_test_init(&argc, &argv, NULL);

    g_test_add_func ("/glob/match/simple", test_glob_match_simple);
    g_test_add_func ("/glob/match/string", test_glob_match_string);
    g_test_add_func ("/glob/match/match", test_glob_match_match);

    return g_test_run();
}

运行结果:

[root@centos7 build]# ./glib_glob_match
/glob/match/simple: a?c is match abc
OK
/glob/match/string: a?c* is match abcdef
OK
/glob/match/match: hello你好* is match hello你好啊hello
OK
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值