在程序員一生的工作中,遇到的最多的數據就是字符串
字符串里面很有可能有很多的不需要的信息
我們需要從中間挑選出我們需要的
如果循環去寫,比較簡單的時候問題不大
規則多了,你的工作量會成倍上升的
為了解決這個問題 ---- 正則表達式
正則表達式 --- 一種規則,用于匹配我們需要的字符/字符串
簡單一點就是一種匹配規則
字符串的處理通過這個正則表達式會變得簡單很多
正則表達式字符分為兩種
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)//解析錯誤成功{//最好補個\0buf[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;//補\0if(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 不顯示文件名