本文的目的是介绍为什么我的正则表达式可以在RegexPlanet和regex101上运行,而不能在我的代码中运行?的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于C++1
本文的目的是介绍为什么我的正则表达式可以在RegexPlanet和regex101上运行,而不能在我的代码中运行?的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于C++11正则表达式详解(regex_match、regex_search和regex_replace)、C语言用regcomp、regexec、regfree和regerror函数实现正则表达式校验、Golang 正则表达式(regexp)、html – 为什么我的嵌入式YouTube视频在Firefox中运行,而不是在Internet Explorer中运行?的知识。
本文目录一览:- 为什么我的正则表达式可以在RegexPlanet和regex101上运行,而不能在我的代码中运行?
- C++11正则表达式详解(regex_match、regex_search和regex_replace)
- C语言用regcomp、regexec、regfree和regerror函数实现正则表达式校验
- Golang 正则表达式(regexp)
- html – 为什么我的嵌入式YouTube视频在Firefox中运行,而不是在Internet Explorer中运行?
为什么我的正则表达式可以在RegexPlanet和regex101上运行,而不能在我的代码中运行?
给定#100=SAMPLE(''Test'',''Test'',
我要提取的字符串100
和Test
。我^#(\d+)=SAMPLE\(''([\w-]+)''.*
为此创建了正则表达式。
我在RegexPlanet和regex101上测试了regex
。两种工具都能给我带来预期的结果,但是当我尝试在代码中使用它时,却找不到匹配的结果。我使用以下代码片段测试正则表达式:
final String line = "#100=SAMPLE(''Test'',''Test'',";final Pattern pattern = Pattern.compile("^#(\\d+)=SAMPLE\\(''([\\w-]+)''.*");final Matcher matcher = pattern.matcher(line);System.out.println(matcher.matches());System.out.println(matcher.find());System.out.println(matcher.group(1));System.out.println(matcher.group(2));
输出是
truefalseException in thread "main" java.lang.IllegalStateException: No match found at java.util.regex.Matcher.group(Matcher.java:536) at java.util.regex.Matcher.group(Matcher.java:496) at Test.main(Test.java:15)
我使用Java 8来编译和运行程序。为什么正则表达式不能与在线工具一起使用,而不能在我的程序中使用?
答案1
小编典典一个Matcher
对象允许您对其进行多次查询,以便您可以查找表达式,获取组,再次查找表达式,获取组,等等。
这意味着在每次调用后,它都会保持状态-匹配成功后产生的组以及继续搜索的位置。
当您连续运行两个匹配/查找方法时,您将得到:
matches()
-匹配字符串的开头,设置组。find()
-尝试在先前匹配/找到的出现之后找到模式的下一个出现,设置组。
但是,当然,在您的情况下,文本不包含 两次
出现的模式,仅包含一次。因此,尽管matches()
成功并设置了适当的组,find()
然后无法找到另一个匹配项,并且这些组无效(匹配/查找失败后无法访问这些组)。
这就是为什么您收到错误消息的原因。
现在,如果你只是玩弄这个,看看之间的区别matches
和find
,那么就没有什么错在节目中有他们两个。但是您需要reset()
在它们之间使用,这将导致find()
不要尝试从matches()
停止的位置继续(如果matches()
成功,它将始终失败)。相反,它将从头开始扫描,就好像您有一个全新的一样Matcher
。它会成功并为您提供团体。
但是正如这里的其他答案所暗示的那样,如果您不只是尝试比较matches
and 的结果find
,而是想要匹配您的模式并获得结果,那么您应该只选择
其中 之一。
matches()
将尝试匹配整个字符串。因此,如果成功,则find()
在它之后运行将永远不会成功-因为它从字符串末尾开始搜索。如果你使用matches()
,你不需要像锚^
,并$
在开始和你的模式的结束。find()
将尝试匹配字符串中的任何位置。它将从左侧开始扫描,但不需要实际的匹配从此处开始。也可以不止一次使用它。lookingAt()
会尝试匹配字符串的开头,但不一定匹配完整的字符串。就像^
在模式开始时有一个锚点一样。
因此,您可以选择其中之一适合自己,然后使用它,然后可以使用组。尝试使用组之前,请始终测试匹配是否成功!
C++11正则表达式详解(regex_match、regex_search和regex_replace)
在C++11中引入了正则表达式。
字符规则
先来了解一下这个字符的含义吧。
字符 | 描述 |
---|---|
\ | 转义字符 |
$ | 匹配字符行尾 |
* | 匹配前面的子表达式任意多次 |
+ | 匹配前面的子表达式一次或多次 |
? | 匹配前面的子表达式零次或一次 |
{m} | 匹配确定的m次 |
{m,} | 匹配至少m次 |
{m,n} | 最少匹配m次,最大匹配n次 |
字符 | 描述 |
---|---|
. | 匹配任意字符 |
x|y | 匹配x或y |
[xyz] | 字符集合,匹配包含的任意一个字符 |
[^xyz] | 匹配未包含的任意字符 |
[a-z] | 字符范围,匹配指定范围内的任意字符 |
[^a-z] | 匹配任何不在指定范围内的任意字符 |
头文件:#include
regex_match
全文匹配,即要求整个字符串符合匹配规则,返回true或false
匹配“四个数字-一个或俩个数字”
#include <iostream> #include <regex> using namespace std; int main() { string str; cin >> str; //\d 表示匹配数字 {4} 长度4个 \d{1,2}表示匹配数字长度为1-2 cout << regex_match(str, regex("\\d{4}-\\d{1,2}")); return 0; }
匹配邮箱 “大小写字母或数字@126/163.com”
int main() { string str; cout << "请输入邮箱:" << endl; while (cin >> str)//匹配邮箱 { if (true == regex_match(str, regex("[a-zA-Z0-9]+@1(26|63)\\.com"))) { break; } cout << "输入错误,请重新输入:" << endl; } cout << "输入成功!" << endl; return 0; }
regex_search
搜索匹配,即搜索字符串中存在符合规则的子字符串。
用法一:匹配单个
#include <iostream> #include <regex> #include <string> using namespace std; int main() { string str = "hello2019-02-03word"; smatch match;//搜索结果 regex pattern("(\\d{4})-(\\d{1,2})-(\\d{1,2})");//搜索规则 ()表示把内容拿出来 if (regex_search(str, match, pattern)) { //提取 年 月 日 cout << "年:" << match[1] << endl; cout << "月:" << match[2] << endl; cout << "日:" << match[3] << endl; //下标从1开始 下标0存的是符合这个搜索规则的起始位置和结束位置 } return 0; }
用法二:匹配多个
#include <iostream> #include <regex> #include <string> using namespace std; int main() { //匹配多个符合要求的字符串 string str = "2019-08-07,2019-08-08,2019-08-09"; smatch match; regex pattern("(\\d{4})-(\\d{1,2})-(\\d{1,2})"); string::const_iterator citer = str.cbegin(); while (regex_search(citer, str.cend(), match, pattern))//循环匹配 { citer = match[0].second; for (size_t i = 1; i < match.size(); ++i) { cout << match[i] << " "; } cout << endl; } return 0; }
regex_replace
替换匹配,即可以将符合匹配规则的子字符串替换为其他字符串。
将字符串中的-替换为/
#include <iostream> #include <regex> using namespace std; int main() { //替换不会修改原串 cout << regex_replace("2019-08-07", regex("-"), "/") << endl; return 0; }
匹配以逗号分隔的字符串(\S表示匹配任意显示字符)
使用正则表达式将所有信息批处理为sql的语句
使用正则表达式1999-10-7 修改为 10/7/1999
先匹配上,再拿小括号获取值 然后替换
然后就可以放在程序中
int main() { string str; cin >> str; cout << regex_replace(str, regex("(\\d{4})-(\\d{1,2})-(\\d{1,2})"), "$2/$3/$1"); return 0; }
将字符串中的/删掉
总结
到此这篇关于C++11正则表达式(regex_match、regex_search和regex_replace)的文章就介绍到这了,更多相关C++11正则表达式内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
- 正则表达式简介及在C++11中的简单使用教程
- c++11中regex正则表达式示例简述
C语言用regcomp、regexec、regfree和regerror函数实现正则表达式校验
前言
首先,祝大家国庆假期玩的嗨皮!可能有的人已经在回家的路上了,是不是都看不到我的真挚祝福了?
C语言对于一些东西的封装比较少,比如正则表达式,但速度快一直使它立于不败之地,今天就要介绍如何用C封装。
一、正则表达式
1、介绍
应该都听过正则吧?主要应用在字符串匹配,而且它是通用的,各种语言都支持。例如可以用它匹配IP地址、邮箱等。举个例子说明一下正则有啥用:
例如,我在的公司,页面用PHP,后台用C,当添加用户邮箱时,我们老大就要求:PHP和C都要对用户输入的用户邮箱进行校验,这时正则表达式就派上用场了。
2、grep命令
我会用grep进行简单的举例,所以要简单介绍一下。
grep是一种查找过滤工具,正则表达式在grep中用来查找符合模式的字符串。其实正则表达式还有一个重要的应用是验证用户输入是否合法,例如用户通过网页表单提交自己的email地址,就需要用程序验证一下是不是合法的email地址,这个工作可以在网页的Javascript中做,也可以在网站后台的程序中做,例如PHP、Perl、Python、Ruby、Java或C,所有这些语言都支持正则表达式,可以说,目前不支持正则表达式的编程语言实在很少见。
egrep相当于grep -E,表示采用Extended正则表达式语法。
注意grep找的是包含某一模式的行,而不是完全匹配某一模式的行。
3、基本语法
对于正则表达式的语法,我只列出比较常见的,基本就够用了,如果有兴趣的可以再去网上学习,去深入了解。
字符类
数量限定符
位置限定符
举例:查找IP的正则
用^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$查找
其它特殊字符
4、分类
大致分为两类:Basic正则和Extended正则
区别:
以上介绍的是grep正则表达式的Extended规范,Basic规范也有这些语法,只是字符?+{}|()应解释为普通字符,要表示上述特殊含义则需要加\转义。如果用grep而不是egrep,并且不加-E参数,则应该遵照Basic规范来写正则表达式。
二、正则表达式相关函数
C语言处理正则表达式常用的函数有regcomp()、regexec()、regfree()和regerror()
C语言中使用正则表达式一般分为三步:
- 编译正则表达式 regcomp()
- 匹配正则表达式 regexec()
- 释放正则表达式 regfree()
下边将对三个函数的详细解释。
1、regcomp函数
功能:这个函数把指定的正则表达式pattern编译成一种特定的数据格式compiled,这样可以使匹配更有效。
原型:int regcomp(regex_t *preg, const char *regex, int cflags);
参数说明:
regex_t 是一个结构体数据类型,用来存放编译后的正则表达式,它的成员re_nsub 用来存储正则表达式中的子正则表达式的个数,子正则表达式就是用圆括号包起来的部分表达式。
参数regex: 是指向我们写好的正则表达式的指针。
参数cflags: 有如下4个值或者是它们或运算(|)后的值:
REG_EXTENDED 以功能更加强大的扩展正则表达式的方式进行匹配。
REG_ICASE 匹配字母时忽略大小写。
REG_NOSUB 不用存储匹配后的结果,只返回是否成功匹配。如果设置该标志位,那么在regexec(在下边介绍)将忽略nmatch和pmatch两个参数。
REG_NEWLINE 识别换行符,这样''$''就可以从行尾开始匹配,''^''就可以从行的开头开始匹配。
2、regexec函数
功能:函数regexec 会使用这个数据在目标文本串中进行模式匹配。
原型:int regexec(const regex_t *preg, const char *string, size_t nmatch,regmatch_t pmatch[], int eflags);
先来介绍下参数4中的regmatch_t结构体:
regmatch_t 是一个结构体数据类型,在regex.h中定义:
typedef struct {
regoff_t rm_so;
regoff_t rm_eo;
} regmatch_t;
成员rm_so 存放匹配文本串在目标串中的开始位置,rm_eo 存放结束位置。通常我们以数组的形式定义一组这样的结构。
参数说明:
preg 是已经用regcomp函数编译好的正则表达式。
string 是目标文本串。
nmatch 是regmatch_t结构体数组的长度。
matchptr regmatch_t类型的结构体数组,存放匹配文本串的位置信息。
eflags 有两个值:
REG_NOTBOL 让特殊字符^无作用
REG_NOTEOL 让特殊字符$无作用
3、regfree函数
功能:可以用这个函数清空regex_t结构体的内容
原型:void regfree(regex_t *preg);
4、regerror函数
功能:当执行regcomp 或者regexec 产生错误的时候,就可以调用这个函数而返回一个包含错误信息的字符串。
原型:size_t regerror(int errcode, const regex_t *preg, char *errbuf,size_t errbuf_size);
参数说明:
errcode 是由regcomp 和 regexec 函数返回的错误代号。
preg 是已经用regcomp函数编译好的正则表达式,这个值可以为NULL。
errbuf 指向用来存放错误信息的字符串的内存空间。
errbuf_size 指明buffer的长度,如果这个错误信息的长度大于这个值,则regerror 函数会自动截断超出的字符串,但他仍然会返回完整的字符串的长度。所以我们可以用如下的方法先得到错误字符串的长度。
三、程序示例
输入两个参数,第一个参数:正则表达式,第二个参数:字符串,校验是否匹配,程序如下:


#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
if (argc != 3) {
printf("Usage: %s RegexString Text\n", argv[0]);
return 1;
}
const char * pregexstr = argv[1];
const char * ptext = argv[2];
regex_t oregex;
int nerrcode = 0;
char szerrmsg[1024] = {0};
size_t unerrmsglen = 0;
if ((nerrcode = regcomp(&oregex, pregexstr, REG_EXTENDED|REG_NOSUB)) == 0) {
if ((nerrcode = regexec(&oregex, ptext, 0, NULL, 0)) == 0) {
printf("%s matches %s\n", ptext, pregexstr);
regfree(&oregex);
return 0;
}
}
unerrmsglen = regerror(nerrcode, &oregex, szerrmsg, sizeof(szerrmsg));
unerrmsglen = unerrmsglen < sizeof(szerrmsg) ? unerrmsglen : sizeof(szerrmsg) - 1;
szerrmsg[unerrmsglen] = ''\0'';
printf("ErrMsg: %s\n", szerrmsg);
regfree(&oregex);
return 1;
}
演示匹配邮箱:
执行:./a.out "^[a-zA-Z0-9]+@[a-zA-Z0-9]+.[a-zA-Z0-9]+" "ldw@itcast.com"
演示结果如下:
总结
希望喜欢的点关注,不迷路哦!会持续更新linux C/C++相关内容,谢谢支持!
Golang 正则表达式(regexp)
Go内置了(regexp包)对正则表达式的支持,这里是一般的正则表达式常规用法的例子。
示例:
package main
import (
"bytes"
"fmt"
"regexp"
)
func main() {
//是否匹配字符串
// .匹配任意一个字符 ,*匹配零个或多个 ,优先匹配更多(贪婪)
match, _ := regexp.MatchString("H(.*)d!", "Hello World!")
fmt.Println(match) //true
//或
match, _ = regexp.Match("H(.*)d!", []byte("Hello World!"))
fmt.Println(match) //true
//或通过`Compile`来使用一个优化过的正则对象
r, _ := regexp.Compile("H(.*)d!")
fmt.Println(r.MatchString("Hello World!")) //true
// 这个方法返回匹配的子串
fmt.Println(r.FindString("Hello World! world")) //Hello World!
//同上
fmt.Println(string(r.Find([]byte("Hello World!")))) //Hello World!
// 这个方法查找第一次匹配的索引
// 的起始索引和结束索引,而不是匹配的字符串
fmt.Println(r.FindStringIndex("Hello World! world")) //[0 12]
// 这个方法返回全局匹配的字符串和局部匹配的字符,匹配最大的子字符串一次。
// 它和r.FindAllStringSubmatch("Hello World! world",1) 等价。 比如
// 这里会返回匹配`H(.*)d!`的字符串
// 和匹配`(.*)`的字符串
fmt.Println(r.FindStringSubmatch("Hello World! world")) //[Hello World! ello Worl]
// 和上面的方法一样,不同的是返回全局匹配和局部匹配的
// 起始索引和结束索引
fmt.Println(r.FindStringSubmatchIndex("Hello World! world")) //[0 12 1 10]
// 这个方法返回所有正则匹配的字符,不仅仅是第一个
fmt.Println(r.FindAllString("Hello World! Held! world", -1)) //[Hello World! Held!]
// 这个方法返回所有全局匹配和局部匹配的字符串起始索引,只匹配最大的串
// 和结束索引
fmt.Println(r.FindAllStringSubmatchIndex("Hello World! world", -1)) //[[0 12 1 10]]
fmt.Println(r.FindAllStringSubmatchIndex("Hello World! Held! world", -1)) //[[0 18 1 16]]
// 为这个方法提供一个正整数参数来限制匹配数量
res, _ := regexp.Compile("H([a-z]+)d!")
fmt.Println(res.FindAllString("Hello World! Held! Hellowrld! world", 2)) //[Held! Hellowrld!]
fmt.Println(r.FindAllString("Hello World! Held! world", 2)) //[Hello World! Held!]
//注意上面两个不同,第二参数是一最大子串为单位计算。
// regexp包也可以用来将字符串的一部分替换为其他的值
fmt.Println(r.ReplaceAllString("Hello World! Held! world", "html")) //html world
// `Func`变量可以让你将所有匹配的字符串都经过该函数处理
// 转变为所需要的值
in := []byte("Hello World! Held! world")
out := r.ReplaceAllFunc(in, bytes.ToUpper)
fmt.Println(string(out))
// 在 b 中查找 reg 中编译好的正则表达式,并返回第一个匹配的位置
// {起始位置, 结束位置}
b := bytes.NewReader([]byte("Hello World!"))
reg := regexp.MustCompile(`\w+`)
fmt.Println(reg.FindReaderIndex(b)) //[0 5]
// 在 字符串 中查找 r 中编译好的正则表达式,并返回所有匹配的位置
// {{起始位置, 结束位置}, {起始位置, 结束位置}, ...}
// 只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项
fmt.Println(r.FindAllIndex([]byte("Hello World!"), -1)) //[[0 12]]
//同上
fmt.Println(r.FindAllStringIndex("Hello World!", -1)) //[[0 12]]
// 在 s 中查找 re 中编译好的正则表达式,并返回所有匹配的内容
// 同时返回子表达式匹配的内容
// {
// {完整匹配项, 子匹配项, 子匹配项, ...},
// {完整匹配项, 子匹配项, 子匹配项, ...},
// ...
// }
// 只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项
reg = regexp.MustCompile(`(\w)(\w)+`) //[[Hello H o] [World W d]]
fmt.Println(reg.FindAllStringSubmatch("Hello World!", -1)) //[[Hello H o] [World W d]]
// 将 template 的内容经过处理后,追加到 dst 的尾部。
// template 中要有 $1、$2、${name1}、${name2} 这样的“分组引用符”
// match 是由 FindSubmatchIndex 方法返回的结果,里面存放了各个分组的位置信息
// 如果 template 中有“分组引用符”,则以 match 为标准,
// 在 src 中取出相应的子串,替换掉 template 中的 $1、$2 等引用符号。
reg = regexp.MustCompile(`(\w+),(\w+)`)
src := []byte("Golang,World!") // 源文本
dst := []byte("Say: ") // 目标文本
template := []byte("Hello $1, Hello $2") // 模板
m := reg.FindSubmatchIndex(src) // 解析源文本
// 填写模板,并将模板追加到目标文本中
fmt.Printf("%q", reg.Expand(dst, template, src, m))
// "Say: Hello Golang, Hello World"
// LiteralPrefix 返回所有匹配项都共同拥有的前缀(去除可变元素)
// prefix:共同拥有的前缀
// complete:如果 prefix 就是正则表达式本身,则返回 true,否则返回 false
reg = regexp.MustCompile(`Hello[\w\s]+`)
fmt.Println(reg.LiteralPrefix())
// Hello false
reg = regexp.MustCompile(`Hello`)
fmt.Println(reg.LiteralPrefix())
// Hello true
text := `Hello World! hello world`
// 正则标记“非贪婪模式”(?U)
reg = regexp.MustCompile(`(?U)H[\w\s]+o`)
fmt.Printf("%q\n", reg.FindString(text)) // Hello
// 切换到“贪婪模式”
reg.Longest()
fmt.Printf("%q\n", reg.FindString(text)) // Hello Wo
// 统计正则表达式中的分组个数(不包括“非捕获的分组”)
fmt.Println(r.NumSubexp()) //1
//返回 r 中的“正则表达式”字符串
fmt.Printf("%s\n", r.String())
// 在 字符串 中搜索匹配项,并以匹配项为分割符,将 字符串 分割成多个子串
// 最多分割出 n 个子串,第 n 个子串不再进行分割
// 如果 n < 0,则分割所有子串
// 返回分割后的子串列表
fmt.Printf("%q\n", r.Split("Hello World! Helld! hello", -1)) //["" " hello"]
// 在 字符串 中搜索匹配项,并替换为 repl 指定的内容
// 如果 rep 中有“分组引用符”($1、$name),则将“分组引用符”当普通字符处理
// 全部替换,并返回替换后的结果
s := "Hello World, hello!"
reg = regexp.MustCompile(`(Hell|h)o`)
rep := "${1}"
fmt.Printf("%q\n", reg.ReplaceAllLiteralString(s, rep)) //"${1} World, hello!"
// 在 字符串 中搜索匹配项,然后将匹配的内容经过 repl 处理后,替换 字符串 中的匹配项
// 如果 repb 的返回值中有“分组引用符”($1、$name),则将“分组引用符”当普通字符处理
// 全部替换,并返回替换后的结果
ss := []byte("Hello World!")
reg = regexp.MustCompile("(H)ello")
repb := []byte("$0$1")
fmt.Printf("%s\n", reg.ReplaceAll(ss, repb))
// HelloH World!
fmt.Printf("%s\n", reg.ReplaceAllFunc(ss,
func(b []byte) []byte {
rst := []byte{}
rst = append(rst, b...)
rst = append(rst, "$1"...)
return rst
}))
// Hello$1 World!
}
小结:
1、
r, _ := regexp.Compile("H(.*)d!")
可用一下代替
r := regexp.MustCompile("H(.*)d!")
两者区别 MustCompile 少一个返回值err
看源码
// Compile parses a regular expression and returns, if successful,
// a Regexp object that can be used to match against text.
//...
// For POSIX leftmost-longest matching, see CompilePOSIX.
func Compile(expr string) (*Regexp, error) {
return compile(expr, syntax.Perl, false)
}
// MustCompile is like Compile but panics if the expression cannot be parsed.
// It simplifies safe initialization of global variables holding compiled regular
// expressions.
func MustCompile(str string) *Regexp {
regexp, err := Compile(str)
if err != nil {
panic(`regexp: Compile(` + quote(str) + `): ` + err.Error())
}
return regexp
}
2、regexp的处理byte的方法都有个string方法对应,两者功能一样。
例如:
regexp.Match()
和
regexp.MatchString()
links
- 目录
html – 为什么我的嵌入式YouTube视频在Firefox中运行,而不是在Internet Explorer中运行?
<object width="425" height="344"> <param name="movie" value="**URL**"> </param> <param name="allowFullScreen" value="true"> </param> <embed src="**URL**" type="application/xshockwave-flash" allowfullscreen="true" width="425" height="344"> </embed> </object>
它适用于Firefox,但为什么不在Internet Explorer中呢?
我是一个全新的网络开发人员,所以我遇到了你退伍军人习惯的所有这些奇妙的不一致;)
解决方法
<object type="application/x-shockwave-flash" data="VID_URL" width="425" height="344"> <param name="movie" value="VID_URL" /> </object>
关于为什么我的正则表达式可以在RegexPlanet和regex101上运行,而不能在我的代码中运行?的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于C++11正则表达式详解(regex_match、regex_search和regex_replace)、C语言用regcomp、regexec、regfree和regerror函数实现正则表达式校验、Golang 正则表达式(regexp)、html – 为什么我的嵌入式YouTube视频在Firefox中运行,而不是在Internet Explorer中运行?等相关内容,可以在本站寻找。
本文标签: