第二十天(正则表达式与功能实际运用)

发布于:2025-07-27 ⋅ 阅读:(18) ⋅ 点赞:(0)

在程序员一生的工作中,遇到的最多的数据就是字符串
    字符串里面很有可能有很多的不需要的信息
    我们需要从中间挑选出我们需要的
    如果循环去写,比较简单的时候问题不大
        规则多了,你的工作量会成倍上升的
    为了解决这个问题 ---- 正则表达式

正则表达式 --- 一种规则,用于匹配我们需要的字符/字符串
    简单一点就是一种匹配规则
    字符串的处理通过这个正则表达式会变得简单很多

正则表达式字符分为两种
    1 普通字符 -- 只代表这个字符本身
        a b c d e f......
    2 元字符:有特殊意义的字符
        它不代表字符本身的意思,另外赋予它意思了
            如:scanf printf里面的%

正则表达式里面的元字符
    .   : 匹配任意的一个单个字符
    []  : 字符组,但是它只代表其中一个
            []里面可能会写很多个字符,但是只代表一个字符
            只能有一个字符和[]里面的字符去匹配
            挑里面有的去匹配
            如:[abcdefg] -> 43720jklrhj423urlkehk23hijka
                后面的字符串只有e 和 a才能被匹配
            这个[]里面也有一个元字符 -
            -:表示从ASCII码开始到ASCII码结束这一节所有的字符
                有开始有结束才代表连接,否则就是-自己本身
            [A-Z]: 表示 A到Z中间所有的字符,只会匹配其中一个
            [a-z]: 匹配一个小写字母
            [A-Za-z]:匹配
            [0-9]:匹配数字字符
            [-9]:这个没有开始,那么-就是它自己
                匹配-或者9字符
    ^   : 排除字符,把它们排除掉
        [^0-9] : 排除所有的数字字符,其它的字符都可以和我匹配
        [^0-9A-Za-z] : 排除数字字符和字母

    字母  数字这些比较特殊,因此会有东西直接表示
        \d  : 匹配数字字符
        \D  : 排除数字字符
        \w  : 匹配数字字母下划线
        \W  : 排除数字字母下划线
        \s  : 空白字符
        \S  : 非空字符

匹配多个字符
    +   : 匹配1个或者多个先前字符
        [A-Z]+ 匹配长度至少为1的大写字母
            [A-Z]
            [A-Z][A-Z]
            [A-Z][A-Z][A-Z]
            [A-Z][A-Z][A-Z][A-Z]
            ........
        dahsjkAbc  -> 只有A可以匹配
        dhsajkDEf   -> DE可以匹配
        dasdwqda    -> 没有
            A
            BC
            DFG
            .....

    *   :匹配0个或者多个先前字符
        [A-Z]*
            空的
            [A-Z]
            [A-Z][A-Z]
            [A-Z][A-Z][A-Z]
            [A-Z][A-Z][A-Z][A-Z]
            ........

    ?   : 匹配0个或者1个先前字符
        [A-Z]?
            空的
            [A-Z]

    我们也可以指定数量来进行匹配
        {数字}
        a{3} 
            aaa
        [A-Z]{3}
            [A-Z][A-Z][A-Z]
    指定数量里面我们也可以给范围
        {最小数量,最大数量}
        [A-Z]{1,3}
            [A-Z]
            [A-Z][A-Z]
            [A-Z][A-Z][A-Z]
        如果没有最大数量表示上不封顶

    ()被看成是一个整体,这个整体我们叫子模式
        (abc){1,3} 
            abc
            abcabc
            abcabcabc
        abc{1,3} -> 区分
            abc
            abcc
            abccc
    (|) 二选一
        (abc|123){1,2}
            abc
            abcabc
            abc123
            123
            123123
            123abc
    \ 转义字符
        \.  ->普通的.
            \d.c -> 1.c 11c 1cc 2cc 3dc
            \d\.c -> 1.c 2.c 3.c
        \\  ->普通的\
        \*  ->普通的*

    ipv4 : 用4个字节表示一个ip地址
        xxx.xxx.xxx.xxx
            192.168.5.250   
    有一个字符串待匹配
        dhasjkdhwq3123.342432.123.34.53.6dashjk.123.234.12.4dhasjk
        请你写一个正则表达式来匹配ip地址
            [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

我在我的系统里面存了一个pxxxxx.c的这么一个文件,我忘记放哪里了,你帮我找一下
    xxxxx是数字,我不记得有多少个了
        p[0-9]+\.c

c语言支持了正则表达式

NAME
       regcomp, regexec, regerror, regfree - POSIX regex functions

SYNOPSIS
       #include <sys/types.h>
       #include <regex.h>

       int regcomp(regex_t *preg, const char *regex, int cflags);
            preg:编译好了的正则表达式 --- 就是它能看得懂的字节码
                这个玩意儿是一个地址
            regex:你编辑的正则表达式,是一个字符串
                如:"p[0-9]+\.c"    
            cflags: 标志 ,用位域实现的 
                REG_EXTENDED    : 扩展的正则表达式,一般都带上这个标志
                REG_ICASE       :  忽略大小写
                REG_NOSUB       : 忽略子模式
                REG_EXTENDED | REG_ICASE  用扩展的正则表达式并且忽略大小写
            成功返回0,失败返回错误码


            //运行我们的正则表达式
       int regexec(const regex_t *preg, const char *string, size_t nmatch,
                   regmatch_t pmatch[], int eflags);
            preg:编译好了的正则表达式
            string:待匹配字符串
            nmatch:你有多少个模式 1 + n,一般n <= 实际子模式数
                总模式(1) + 子模式(n)
                    "ds(ajh)(kd)wh(jk)"
            pmatch:匹配的信息,也就是匹配的结果
                它是一个数组
                   pmatch = malloc(sizeof(regmatch_t) * nmatch) 
                第一个元素为总模式
                后面的为子模式
                    typedef struct {
                        regoff_t rm_so;//start 开始  待匹配字符串的下标
                        regoff_t rm_eo;//end   结束  待匹配字符串的下标
                    } regmatch_t;
            eflags:一个标志
                一般给0
        返回值:
            成功返回0,你可能会有后续继续的匹配
            失败返回  REG_NOMATCH

       size_t regerror(int errcode, const regex_t *preg, char *errbuf,
                       size_t errbuf_size);
            errcode:错误码
            preg:编译了的正则表达式
            errbuf:存放解析好了的错误信息
            errbuf_size:你给errbuf的最大存储空间
            成功返回实际写入errbuf里面的字节数

       void regfree(regex_t *preg);
            释放preg


//心中有的数 如果是正则表达式是有问题的为1 如果是其它的表示为2 成功是0

int regerror(int errcode, const regex_t *preg, char *errbuf,
                       size_t errbuf_size)
{
    int len = 0;
    switch(errcode)
    {
        case 0:
            len = strlen("success") < errbuf_size ? strlen("success") : errbuf_size;
            strncpy(errbuf,"success",len);
            return len;
        case 1:
            len = strlen("zheng ze biao da shi you wen ti") < errbuf_size ? strlen("zheng ze biao da shi you wen ti") : errbuf_size;
            strncpy(errbuf,"heng ze biao da shi you wen ti",len);
            return len;
        case 2:
            len = strlen("other") < errbuf_size ? strlen("other") : errbuf_size;
            strncpy(errbuf,"other",len);
            return len;
        default:
            return -1;
    }


}    

#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
#include <string.h>


//我们挑网址出来  (www){1}\.[A-Za-z0-9]+\.(com){1}
#define REGEXSTRING "(www){1}\\.[A-Za-z0-9]+\\.(com){1}"

const char * const str = "dsahejkdwqhdsaww.sadhjkdhwww.dashjd.www.baidu.com\
dashjkdhwqjww.baidu.cmwww.hehe.comasdwqwww.123123.comshadjkwqhk";


int main()
{
    //编译我们的正则表达式
    //regex_t * preg = (regex_t *)malloc(sizeof(regex_t));//空间是在堆上面开的  搞完要释放的
    regex_t  preg;//在栈上面开的  代码块弄完自动释放
    int r = regcomp(&preg,REGEXSTRING,REG_EXTENDED);
    char buf[1024] = {0};
    if(r != 0)//错了
    {
        //解析错误信息 
        int l = regerror(r,&preg,buf,1023);
        if(l > 0)//解析错误成功
        {
            //最好补个\0
            buf[l] = 0;
            printf("regcomp error:%s\n",buf);
            return -1;
        }
        printf("不知道什么错误\n");
        return -2;         
    }

    //执行正则表达式
    //返回值如果为0  说明后面还有可能有未匹配到的
    const char * ptr = str;
    regmatch_t pmatch[3];//存放我们的结果
    while(1)
    {
        r = regexec(&preg,ptr,3,pmatch,0);
        if(r != 0)
        {
            break;
        }
        //匹配成功
        for(int i = 0;i < 3;i++)
        {
            printf("[%ld,%ld) -> ",pmatch[i].rm_so + ptr - str,pmatch[i].rm_eo + ptr - str);

            strncpy(buf,ptr + pmatch[i].rm_so,pmatch[i].rm_eo - pmatch[i].rm_so);

            buf[pmatch[i].rm_eo - pmatch[i].rm_so] = 0;//补\0
            if(i == 0)
            {
                printf("总模式:%s\n",buf);
            }
            else
            {
                printf("子模式:%s\n",buf);
            }
        }
        ptr += pmatch[0].rm_eo;//将匹配过的字符串给跳过
    }


    regfree(&preg);


    return 0;
}


//有用正则表达式的命令

find -> 查找
    find [path] [options]
        path:你要查找的路径
            不给默认当前路径

    options:
        -name -> 指定你要查找的名字
            里面有两个通配符可以使用
            * -> 所有的
            ? -> 一个字符
    find ./ -name "*.c" -> 在当前路径下面查找所有的.c文件
    
        -regex -> 用正则表达式来查

    查当前文件夹下面所有的数字.c文件
        find ./ -regex "\d+\.c"

    -type 指定要查找的文件的类型
              b      block (buffered) special 块设备

              c      character (unbuffered) special 字符设备
              d      directory  文件夹
              p      named pipe (FIFO) 有名管道
              f      regular file 普通文件

              l      symbolic link; this is never true if the -L option or the
                     -follow  option is in effect, unless the symbolic link is
                     broken.  If you want to search for symbolic links when -L
                     is in effect, use -xtype.
              s      socket

              D      door (Solaris)

    -size 指定大小
        默认以块为单位
            -size 5
                实际查找文件大小为 5 * 512字节

              `b'    for 512-byte blocks (this is the default if no suffix  is
                     used)  块

              `c'    for bytes 字节

              `w'    for two-byte words 两个字节

              `k'    for Kibibytes (KiB, units of 1024 bytes)

              `M'    for Mebibytes (MiB, units of 1024 * 1024 = 1048576 bytes)

              `G'    for  Gibibytes  (GiB,  units  of  1024  *  1024  * 1024 =
                     1073741824 bytes)

    -delete 找到及删除

    -exec commod {} \;
        找到及执行 commod 
            {}为执行结果的占位符
        find ./ -name "*.h" -exec tar -jcvf 1.tar.bz2 {} \; 
            找到当前路径下面所有的.h文件,然后将其压缩为 1.tar.bz2

grep:在一个文件里面查找对应的字符串
    grep [OPTIONS] PATTERN [FILE...]
            FILE你的待匹配的文件路径名
            PATTERN : 正则表达式

        OPTIONS:
            -n 显示查找到的字符串所在行
            -E  用扩展的正则表达式

            -i 忽略大小写

            -# 同时显示匹配的上下#行


            -c 打印每个文件匹配行的个数
            
            -H 显示文件名

            -h 不显示文件名


网站公告

今日签到

点亮在社区的每一天
去签到