正则表达式简介以及C++/Java实现

由于最近的项目中用到了正则表达式,正好也遇到了一个面试题,题中也有对正则表达式就行考察,所以简单学习一下Regular Expression,然后以一道笔试题的实现来作为练习。

首先可以熟悉一下正则表达式的概念:http://baike.baidu.com/view/94238.htm

常用的正则表达式
正则表达式 匹配 举例
x 指定字符x Java 与 Java 匹配
. 任意单个字符 Java 与 J..a匹配
(ab|cd) ab或cd ten与t(en|im)匹配
[abc] a,b或c Java与Ja[uvwx]a匹配
[^abc] 除a,b或c以外的任何字符 Java与Ja[^ars]a
[a-z] a到z Java与[A-M]av[a-d]匹配
[^a-z] 除a-z之间的任何字符 Java与Java[^b-d]匹配
[a-e[m-p]] a到e或m到p Java与[A-G[I-M]]av[a-d]匹配
[a-e&&[c-p]] a-e与c-p的交 Java与[A-P&&[I-M]]av[a-d]匹配
\d 一个数字,[1-9] Java2与"Java[\\d]"匹配
\D 非数字 $Java与"[\\D][\\D]ava"匹配
\w 词的一个字符 Java与"[\\w]ava"匹配
\W 非词的一个字符 $Java与"[\\W][\\w]ava"匹配
\s 一个空白字符 "Java 2"与"Java\\s2"匹配
\S 一个非空白字符
p* 模式p的0次或多次出现
p+ 模式p的1次或多次出现
p? 模式p的0次或1次出现
p{n} 模式p的n次精确出现
p{n,} 模式p的至少n次出现
p{n,m} 模式p的n到m次(包含m和n)出现

e.g1:社会安全数字的模式为 xxx-xx-xxxx,其中x为一个 数字。社会安全数字的一个正则表达式可以描述为:
[\\d]{3}-[\\d]{2}-[\\d]{4}

e.g2:一个以0,2,4,6,8结尾的偶数,偶数的模式可以描述为:
[\\d]*[02468]

e.g3:电话号码的模式为(xxx)xxx-xxxx,其中x为数字,第一个数字不能为0。电话号码的正则表达式可表示为:
\\([1-9][\\d]{2}\\)[\\d]{3}-[\\d]{4}
备注:括号()是特殊的符号,在正则表达式中用来把模式分组。在正则表达式中若表示(或),必须使用\\(和\\)。

e.g4:假设姓包括25个子母中的大部分,第一个部分大写。姓的模式可以描述为:
[A-Z][a-zA-Z][1,24]
注意,不能在正则表达式中使用任意空白。例如,[A-Z][\\a-zA-Z]{1.24}是错的。

e.g5:"Welcome to (Java|HTML)"匹配的是:"Welcome to Java"或"Welcome to HTML"

e.g6:和所有字符串匹配的正则表达式是 ".*"

下面是某个IT公司的笔试题:

Please write a program to complete the following task (C++/Perl/Python/Shell allowed):

Read several lines of text from STDIN,and

1)filter out all the email addresses from the input text;

2)print a statistic table of how many times each email server is used.

Example:

Input:

CEO of NVIDIA: jenhsun.huang@nvidia.com (the address if fake :)

Some of my favorite writers (they are all fake :)

scott.meyers@brown.edu

herb_sutter@dev.microsoft.com

ericgamma@google.com - known as GoF

jcarmack@idsoftware.com

mark_kilgard@nvidia.com

andrew.rubin@google.com

NVIDIA recruiting team: hr@nvidia.com

Output:

1)

jenhsun.huang@nvidia.com

scott.meyers@brown.edu

herb_sutter@dev.microsoft.com

ericgamma@google.com

jcarmack@idsoftware.com

mark_kilgard@nvidia.com

andrew.rubin@google.com

hr@nvidia.com

2)

nvidia.com: 3

google.com: 2

brown.edu: 1

dev.microsoft.com: 1

idsoftware.com 1


题目大意:从一个文本中读取信息,然后将所有邮箱都打印出来,并且统计每个邮箱“@”之后的字符串出现的次数,从输出的结果来看,应该还要按照出现的次数进行排序再输出结果。


程序流程:

1)将文本文件标准读入。

2)对于输入的字符串判断是不是和正则表达式匹配(Email的正则表达式),如果匹配进入3),否则2)。

3)将匹配的字符串(说明是Email)的"@"字符之后的子串提取出来,然后用map存储子串。

4)统计相同子串出现的次数,按照次数进行排序。

5)将map中的<key,value>对输出到文件中。


Java中的正则表达式判断:

Java中的正则表达式判断很简单,假设目标串为target,正则表达式模式串为pattern,那么判断二者匹配的方法为:target.match(pattern),如果返回真则表示匹配成功。


C中的正则表达式的判断:

C中的正则表达式的判断则相对复杂,首先要将正则表达式模式串pattern编译成为一个结构体compiled,然后将目标串target与compiled进行匹配。主要的两个函数为:

int regcomp(regex_t *compiled,const char *pattern,int cflags)
功能:
将要进行匹配的正则表达式pattern进行编译,做匹配前的准备工作
int regexec(const regex_t *compiled,const char *target,size_t nmatch,regmatch_t pmatch[],int eflags)
功能:
用来检测字符串target是否匹配正则表达式compiled


那么,现在就根据那道题目将代码附上(其中regular_expression.txt文件就是题目中input的内容):

Java实现:

package String;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.Map.Entry;

public class Regex {
	
	private static class ValueComparator implements Comparator<Map.Entry<String,Integer>>{
		@Override
		public int compare(Map.Entry<String,Integer> m,Map.Entry<String,Integer> n) {
			
			return n.getValue()-m.getValue();
		}	
	}
	
	public static void main(String [] args) throws FileNotFoundException{

		//6~18个字符,可使用字母、数字、下划线,需以字母开头
		String pattern = "^[a-zA-Z][\\d\\w\\.]{1,17}@[\\d\\w\\.]{1,}";  //定义模式串pattern
		
		File file = new File("regular_expression.txt");
		Scanner input = new Scanner(file);
		HashMap map = new HashMap<String,Integer>();
		int val;
		while(input.hasNext()){           //依次读入文件中的字符串
			String s = input.next();
			s.trim();
			if(s.matches(pattern)){   //如果是匹配则说明是email
				System.out.println(s);
				s = s.substring(s.lastIndexOf('@')+1);  //提取"@"字符后面的子串
				if(map.get(s)==null){
					map.put(s,1);
				}else{
					val = (Integer)map.get(s)+1;
					map.put(s,val);
				}
			}
		}
		
		ArrayList<Map.Entry<String,Integer>> list = new ArrayList<Map.Entry<String,Integer>>(map.entrySet());

		Regex.ValueComparator vc = new ValueComparator();
		
		Collections.sort(list,vc);   //按照value值进行排序

		Iterator listItr = list.iterator();  //迭代输出结果
		while(listItr.hasNext()){
			Map.Entry<String,Integer> entry = (Map.Entry<String,Integer>) listItr.next();
			System.out.println(entry.getKey()+" : "+entry.getValue());
		}
	}
}


结果:


C/C++实现:

#include<iostream>
#include<stdio.h>
#include<regex.h>
#include<string.h>
#include<fstream>
#include<map>
#include<vector>
#include<algorithm>

using namespace std;

int cflags = REG_EXTENDED,valid,i;
regex_t compiled;
const char *pattern = "[\\d\\w\\.\\_]*+@+[\\d\\w\\.]*";  //定义模式串pattern
char *target = new char[100];
ifstream fin;
ofstream fout;
map<string,int>  map_regex;
typedef pair<string,int> PAIR;

struct CmpByValue
{
	bool operator()(const PAIR& lhs,const PAIR& rhs)
	{
		return lhs.second > rhs.second;
	}
};

void OutputResults()
{ 
	vector<PAIR> vector_regex(map_regex.begin(),map_regex.end());//将map_regex中的内容转存到vector_regex中去。
	sort(vector_regex.begin(),vector_regex.end(),CmpByValue());//根据比较函数进行排序 
	for(int i=0;i<vector_regex.size();i++)
	{
		fout<<vector_regex[i].first<<" : "<<vector_regex[i].second<<endl;
	}
}

void RegexMatch(char * target)
{
	regcomp(&compiled,pattern,cflags);
	valid = regexec(&compiled,target,NULL,0);
	if(valid == REG_NOMATCH)
	{
		//cout<<"no match"<<endl;
	}
	else if(valid == 0)
	{
		cout<<target<<" matches "<<pattern<<endl;
		
		string::size_type pos;
		string target_str(target);
		string sub_str;
		pos = target_str.find("@");
		sub_str = target_str.substr(pos+1,target_str.length()-pos-1);//提取子串 

        //统计子串出现的频率 
		if(map_regex[sub_str]==0)	
		{
			map_regex[sub_str]=1;
		}
		else
		{
			map_regex[sub_str]++;
		}
	}
	regfree(&compiled);
}

int main(int argc,char ** argv)
{
	fin.open("regular_expression.txt");
	if(!fin)
	{
		cout<<"open the file failure"<<endl;
		return 0;
	}
	fout.open("result.txt");

	while(fin>>target)
	{
		RegexMatch(target);
	}	
	OutputResults();
	fin.close();
	fout.close();
	return 0;
}


屏幕打印信息:


输出文件result.txt:

jenhsun.huang@nvidia.com
scott.meyers@brown.edu
herb_sutter@dev.microsoft.com
ericgamma@google.com
jcarmack@idsoftware.com
mark_kilgard@nvidia.com
andrew.rubin@google.com
hr@nvidia.com
nvidia.com : 3
google.com : 2
brown.edu : 1
dev.microsoft.com : 1
idsoftware.com : 1


参考:


转载注明出处:http://www.jb51.cc/article/p-udyrqdln-mp.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


jquery.validate使用攻略(表单校验) 目录 jquery.validate使用攻略1 第一章&#160;jquery.validate使用攻略1 第二章&#160;jQuery.validate.js API7 Custom selectors7 Utilities8 Validato
/\s+/g和/\s/g的区别 正则表达式/\s+/g和/\s/g,目的均是找出目标字符串中的所有空白字符,但两者到底有什么区别呢? 我们先来看下面一个例子: let name = &#39;ye wen jun&#39;;let ans = name.replace(/\s/g, &#39;&#3
自整理几个jquery.Validate验证正则: 1. 只能输入数字和字母 /^[0-9a-zA-Z]*$/g jQuery.validator.addMethod(&quot;letters&quot;, function (value, element) { return this.optio
this.optional(element)的用法 this.optional(element)是jquery.validator.js表单验证框架中的一个函数,用于表单控件的值不为空时才触发验证。 简单来说,就是当表单控件值为空的时候不会进行表单校验,此函数会返回true,表示校验通过,当表单控件
jQuery.validate 表单动态验证 实际上jQuery.validate提供了动态校验的方法。而动态拼JSON串的方式是不支持动态校验的。牺牲jQuery.validate的性能优化可以实现(jQuery.validate的性能优化见图1.2 jQuery.validate源码 )。 也可
自定义验证之这能输入数字(包括小数 负数 ) &lt;script type=&quot;text/javascript&quot;&gt; function onlyNumber(obj){ //得到第一个字符是否为负号 var t = obj.value.charAt(0); //先把非数字的都
// 引入了外部的验证规则 import { validateAccountNumber } from &quot;@/utils/validate&quot;; validator.js /*是否合法IP地址*/ export function validateIP(rule, value,cal
VUE开发--表单验证(六十三) 一、常用验证方式 vue 中表单字段验证的写法和方式有多种,常用的验证方式有3种: data 中验证 表单内容: &lt;!-- 表单 --&gt; &lt;el-form ref=&quot;rulesForm&quot; :rules=&quot;formRul
正则表达式 座机的: 例子: 座机有效写法: 0316-8418331 (010)-67433539 (010)67433539 010-67433539 (0316)-8418331 (0316)8418331 正则表达式写法 0\d{2,3}-\d{7,8}|\(?0\d{2,3}[)-]?\d
var reg = /^0\.[1-9]{0,2}$/;var linka = 0.1;console.log (reg.test (linka)); 0到1两位小数正则 ^(0\.(0[1-9]|[1-9]{1,2}|[1-9]0)$)|^1$ 不含0、0.0、0.00 // 验证是否是[1-10
input最大长度限制问题 &lt;input type=&quot;text&quot; maxlength=&quot;5&quot; /&gt; //可以 &lt;input type=&quot;number&quot; maxlength=&quot;5&quot; /&gt; //没有效
js输入验证是否为空、是否为null、是否都是空格 目录 1.截头去尾 trim 2.截头去尾 会去掉开始和结束的空格,类似于trim 3.会去掉所有的空格,包括开始,结束,中间 1.截头去尾 trim str=str.trim(); // 强烈推荐 最常用、最实用 or $.trim(str);
正则表达式语法大全 字符串.match(正则):返回符合的字符串,若不满足返回null 字符串.search(正则):返回搜索到的位置,若非一个字符,则返回第一个字母的下标,若不匹配则返回-1 字符串.replace(正则,新的字符串):找到符合正则的内容并替换 正则.test(字符串):在字符串中
正整数正则表达式正数的正则表达式(包括0,小数保留两位): ^((0{1}.\d{1,2})|([1-9]\d.{1}\d{1,2})|([1-9]+\d)|0)$正数的正则表达式(不包括0,小数保留两位): ^((0{1}.\d{1,2})|([1-9]\d.{1}\d{1,2})|([1-9]+
JS 正则验证 test() /*用途:检查输入手机号码是否正确输入:s:字符串返回:如果通过验证返回true,否则返回false /function checkMobile(s){var regu =/[1][3][0-9]{9}$/;var re = new RegExp(regu);if (r
请输入保留两位小数的销售价的正则: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/ 1.只能输入英文 &lt;input type=&quot;text&quot; onkeyup=&quot;value
判断价格的正则表达式 价格的正则表达式 /(^[1-9]\d*(\.\d{1,2})?$)|(^0(\.\d{1,2})?$)/; 1 解析:价格符合两种格式 ^ [1-9]\d*(.\d{1,2})?$ : 1-9 开头,后跟是 0-9,可以跟小数点,但小数点后要带上 1-2 位小数,类似 2,2
文章浏览阅读106次。这篇文章主要介绍了最实用的正则表达式整理,比如校验邮箱的正则,号码相关,数字相关等等,本文给大家列举的比较多,需要的朋友可以参考下。_/^(?:[1-9]d*)$/ 手机号
文章浏览阅读1.2k次。4、匹配中的==、an==、== an9、i9 == "9i"和99p==请注意下面这部分的作用,它在匹配中间内容的时候排除了说明:当html字符串如下时,可以匹配到两处,表示匹配的字符串不包含and且不包含空白字符。说明:在上面的正则表达式中,_gvim正则表达式匹配不包含某个字符串
文章浏览阅读897次。【代码】正则表达式匹配a标签的href。_auto.js 正则匹配herf