C#的字符串和正则表达式
字符串
字符串是由一系列字符组成的文本数据,可以用双引号括起来表示,例如:“Hello”。C#中的字符串是不可变的,也就是说,一旦创建了一个字符串对象,就不能修改它的内容。如果要对字符串进行操作,如拼接、替换、删除等,就需要创建一个新的字符串对象。
C#提供了一些内置的方法和属性来处理字符串,例如:
- Length: 返回字符串的长度,即字符的个数。
- IndexOf: 返回指定字符或子字符串在字符串中第一次出现的位置,如果没有找到,则返回-1。
- LastIndexOf: 返回指定字符或子字符串在字符串中最后一次出现的位置,如果没有找到,则返回-1。
- Substring: 返回字符串的一个子串,可以指定开始位置和长度。
- ToUpper: 返回一个新的字符串,其中所有字符都转换为大写。
- ToLower: 返回一个新的字符串,其中所有字符都转换为小写。
- Trim: 返回一个新的字符串,其中删除了开头和结尾的空白字符。
- Replace: 返回一个新的字符串,其中用指定的字符串替换了原字符串中出现的所有指定的字符串。
- Split: 返回一个字符串数组,其中包含了用指定的分隔符分割原字符串得到的子串。
- Join: 返回一个新的字符串,其中用指定的分隔符连接了一个字符串数组中的所有元素。
例如:
using System;
namespace StringDemo
{
class Program
{
static void Main(string[] args)
{
string s = "Hello World";
Console.WriteLine(s.Length); // 11
Console.WriteLine(s.IndexOf('o')); // 4
Console.WriteLine(s.LastIndexOf('o')); // 7
Console.WriteLine(s.Substring(6)); // World
Console.WriteLine(s.Substring(0, 5)); // Hello
Console.WriteLine(s.ToUpper()); // HELLO WORLD
Console.WriteLine(s.ToLower()); // hello world
Console.WriteLine(s.Trim()); // Hello World
Console.WriteLine(s.Replace("World", "C#")); // Hello C#
string[] words = s.Split(' ');
foreach (string word in words)
{
Console.WriteLine(word); // Hello \n World
}
string t = string.Join("-", words);
Console.WriteLine(t); // Hello-World
}
}
}
正则表达式
正则表达式是一种强大的工具,可以用来匹配、提取和替换文本中的特定模式。本文给出了一些常用的正则表达式模式的示例和解释,以及如何在C#中使用Regex类来应用这些模式。正则表达式的语法和功能很丰富,有很多细节和技巧需要掌握,因此建议读者进一步学习和练习正则表达式的使用。
正则表达式是由普通字符(如英文字母)以及特殊字符(也称为元字符)组成的一种文字模式。这种文字模式可以用来检查字符串的值是否满足一定的规则,例如:验证输入的邮箱是否合法、输入的身份证号码是否合法、输入的用户名是否满足条件等。也可以进行字符串的替换和提取,例如:将文本中的敏感词替换为星号、从网页源码中提取链接地址等。
正则表达式的基本语法如下:
- ^ : 匹配字符串的开头。
- $ : 匹配字符串的结尾。
- . : 匹配任意除了\n以外的字符。
- \ : 转义字符,用来取消元字符的特殊含义,或者表示特殊字符,如\t表示制表符。
- [] : 匹配方括号中的任意一个字符,如[abc]匹配a、b或c。
- [^] : 匹配方括号中没有出现的任意一个字符,如[^abc]匹配除了a、b或c以外的任意字符。
- -: 表示范围,如[a-z]匹配a到z之间的任意一个小写字母。
- | : 表示或者,如a|b匹配a或b。
- () : 表示分组,用来限定作用范围或者捕获子串,如(a|b)c匹配ac或bc,(a|b)c\1匹配aca或bcb。
- *: 表示匹配前面的字符0次或多次,如a*匹配空串或任意个a。
- +: 表示匹配前面的字符1次或多次,如a+匹配至少一个a。
- ? : 表示匹配前面的字符0次或1次,如a?匹配空串或一个a。
- {n} : 表示恰好匹配前面的字符n次,如a{3}匹配三个a。
- {n,m} : 表示至少匹配前面的字符n次,至多m次,如a{2,4}匹配两个到四个a。
- {n,} : 表示至少匹配前面的字符n次,如a{2,}匹配至少两个a。
- \d : 表示任意一个数字,相当于[0-9]。
- \D : 表示任意一个非数字,相当于[^0-9]。
- \w : 表示任意一个字母或数字或下划线,相当于[a-zA-Z0-9_]。
- \W : 表示任意一个非字母或数字或下划线,相当于[^a-zA-Z0-9_]。
- \s : 表示任意一个空白字符(包括空格、换行、制表符等)。
- \S : 表示任意一个非空白字符(除空格、换行、制表符等)。
- \b : 表示单词边界,即字与空格之间的位置。
- \B : 表示非单词边界,即字与字之间的位置。
- \A : 表示字符串的开始位置,类似于^,但不受多行模式的影响。
- \Z : 表示字符串的结束位置,类似于$,但不受多行模式的影响。
- \z : 表示字符串的绝对结束位置,不允许有换行符存在。
- \G : 表示上一次匹配结束的位置。
在C#中,要使用正则表达式,需要引用System.Text.RegularExpressions命名空间,该命名空间提供了Regex类和相关的类,如Match、Group、Capture等。Regex类是正则表达式引擎的核心类,它提供了一系列的静态方法和实例方法来执行正则表达式操作,如匹配、替换、分割等。常用的方法有:
- Regex.IsMatch(string input, string pattern) : 静态方法,判断输入字符串是否匹配指定的正则表达式模式,返回布尔值。
- Regex.Match(string input, string pattern) : 静态方法,在输入字符串中搜索指定的正则表达式模式,并返回第一个匹配项,返回Match对象。
- Regex.Matches(string input, string pattern) : 静态方法,在输入字符串中搜索指定的正则表达式模式,并返回所有匹配项的集合,返回MatchCollection对象。
- Regex.Replace(string input, string pattern, string replacement) : 静态方法,在输入字符串中搜索指定的正则表达式模式,并用指定的替换字符串替换所有匹配项,返回替换后的字符串。
- Regex.Split(string input, string pattern) : 静态方法,在输入字符串中搜索指定的正则表达式模式,并根据匹配项将字符串分割为子字符串数组,返回字符串数组。
- Regex(string pattern) : 构造函数,创建一个Regex对象,表示指定的正则表达式模式。
- Regex(string pattern, RegexOptions options) : 构造函数,创建一个Regex对象,表示指定的正则表达式模式,并指定一些选项来修改匹配行为,如忽略大小写、多行模式等。
- IsMatch(string input) : 实例方法,判断输入字符串是否匹配当前Regex对象表示的正则表达式模式,返回布尔值。
- Match(string input) : 实例方法,在输入字符串中搜索当前Regex对象表示的正则表达式模式,并返回第一个匹配项,返回Match对象。
- Matches(string input) : 实例方法,在输入字符串中搜索当前Regex对象表示的正则表达式模式,并返回所有匹配项的集合,返回MatchCollection对象。
- Replace(string input, string replacement) : 实例方法,在输入字符串中搜索当前Regex对象表示的正则表达式模式,并用指定的替换字符串替换所有匹配项,返回替换后的字符串。
- Split(string input) : 实例方法,在输入字符串中搜索当前Regex对象表示的正则表达式模式,并根据匹配项将字符串分割为子字符串数组,返回字符串数组。
Match类表示一个正则表达式匹配项,它包含了一些属性和方法来获取匹配结果的信息,如:
- Success : 布尔属性,表示是否成功匹配。
- Value : 字符串属性,表示匹配项的值。
- Index : 整数属性,表示匹配项在输入字符串中开始的位置。
- Length : 整数属性,表示匹配项在输入字符串中占用的长度。
- Groups : GroupCollection属性,表示匹配项包含的分组集合。每个分组对应一个括号内的子表达式。第0个分组是整个匹配。
- NextMatch() : 实例方法,返回输入字符串中下一个匹配项,返回Match对象。
Group类表示一个正则表达式分组,它包含了一些属性和方法来获取分组结果的信息,如:
- Success : 布尔属性,表示是否成功匹配。
- Value : 字符串属性,表示分组的值。
- Index : 整数属性,表示分组在输入字符串中开始的位置。
- Length : 整数属性,表示分组在输入字符串中占用的长度。
- Captures : CaptureCollection属性,表示分组包含的捕获集合。每个捕获对应一个子表达式在输入字符串中出现的位置和值。如果子表达式没有重复出现,则捕获集合只有一个元素,与分组相同。
Capture类表示一个正则表达式捕获,它包含了一些属性来获取捕获结果的信息,如:
- Value : 字符串属性,表示捕获的值。
- Index : 整数属性,表示捕获在输入字符串中开始的位置。
- Length : 整数属性,表示捕获在输入字符串中占用的长度。
以上是正则表达式在C#中的基本用法和应用场景,以及如何编写有效的正则表达式模式。正则表达式是一种强大而灵活的工具,可以用来处理各种文本相关的问题。但是正则表达式也有一些局限性和缺点,例如:
- 正则表达式不能解决所有的文本问题,有些问题可能需要更复杂的逻辑或算法来处理。
- 正则表达式可能很难理解和调试,特别是当模式很长或很复杂时。
- 正则表达式可能影响性能,特别是当模式很复杂或输入字符串很长时。
因此,在使用正则表达式时,应该根据具体的问题和需求来选择合适的模式和方法,并注意避免一些常见的错误和陷阱。同时,也应该利用一些工具和资源来帮助学习和测试正则表达式,例如:
- 正则表达式在线测试工具:可以在网页上输入正则表达式和测试字符串,并实时查看匹配结果和详细信息。例如:https://regex101.com/ 、 https://regexr.com/ 、 https://www.regexpal.com/ 等。
- 正则表达式在线生成工具:可以根据用户输入的条件和选项,自动生成符合要求的正则表达式。例如:https://regex-generator.olafneumann.org/ 、 https://txt2re.com/ 、 https://www.regextester.com/generate 等。
- 正则表达式在线学习教程:可以通过互动的方式学习正则表达式的基本概念和语法,并进行练习和测试。例如:https://regexone.com/ 、 https://www.hackerrank.com/domains/regex 、 https://www.codecademy.com/learn/learn-regex 等。
正则表达式实例
下面给出一些使用正则表达式的实例,可以参考和学习。
验证邮箱地址
邮箱地址的一般格式是:用户名@域名,其中用户名可以包含字母、数字、下划线、点号等字符,域名可以包含字母、数字、点号等字符,但不能以点号结尾。一个可能的正则表达式是:
Regex reg = new Regex(@"^\w+([\.\-]\w+)*@\w+([\.\-]\w+)*\.\w+#34;);
这个正则表达式的意思是:
- ^ : 匹配字符串的开头。
- \w+ : 匹配一个或多个单词字符。
- ([.-]\w+)* : 匹配零次或多次由点号或连字符和单词字符组成的子串。
- @ : 匹配@符号。
- \w+([.-]\w+)* : 同上,匹配域名的部分。
- .\w+ : 匹配由点号和单词字符组成的后缀,如.com或.cn等。
- $ : 匹配字符串的结尾。
例如:
using System;
using System.Text.RegularExpressions;
namespace EmailDemo
{
class Program
{
static void Main(string[] args)
{
string[] emails = { "abc@gmail.com", "xyz@hotmail.com", "123@163.com", "456.qq.com", "789.@sina.com" };
Regex reg = new Regex(@"^\w+([\.\-]\w+)*@\w+([\.\-]\w+)*\.\w+#34;);
foreach (string email in emails)
{
Console.WriteLine("{0} is {1}valid email address.", email, reg.IsMatch(email) ? "" : "not ");
}
}
}
}
输出:
abc@gmail.com is valid email address.
xyz@hotmail.com is valid email address.
123@163.com is valid email address.
456.qq.com is valid email address.
789.@sina.com is not valid email address.
提取URL中的参数
URL中通常会包含一些参数,用?和&分隔,例如:https://www.xxx.com/search?q=c%23&qs=n&form=QBLH。如果想要提取出参数的名称和值,可以使用正则表达式:
Regex reg = new Regex(@"[?&](\w+)=(\w+)");
这个正则表达式的意思是:
- [?&] : 匹配?或&符号,表示参数的开始。
- (\w+) : 匹配一个或多个单词字符,表示参数的名称,并捕获到第一个组中。
- = : 匹配=符号,表示参数的赋值。
- (\w+) : 同上,匹配一个或多个单词字符,表示参数的值,并捕获到第二个组中。
例如:
using System;
using System.Text.RegularExpressions;
namespace UrlDemo
{
class Program
{
static void Main(string[] args)
{
string url = "https://www.xxx.com/search?q=c%23&qs=n&form=QBLH";
Regex reg = new Regex(@"[?&](\w+)=(\w+)");
MatchCollection matches = reg.Matches(url);
foreach (Match match in matches)
{
Console.WriteLine("Parameter name: {0}", match.Groups[1].Value);
Console.WriteLine("Parameter value: {0}", match.Groups[2].Value);
Console.WriteLine();
}
}
}
}
输出:
Parameter name: q
Parameter value: c%23
Parameter name: qs
Parameter value: n
Parameter name: form
Parameter value: QBLH
验证手机号码
手机号码的一般格式是:以1开头的11位数字,其中第二位可以是3-9的任意数字。一个可能的正则表达式是:
Regex reg = new Regex(@"^1[3-9]\d{9}#34;);
这个正则表达式的意思是:
- ^ : 匹配字符串的开头。
- 1 : 匹配数字1。
- [3-9] : 匹配3到9中的任意一个数字。
- \d{9} : 匹配9个任意数字。
- $ : 匹配字符串的结尾。
例如:
using System;
using System.Text.RegularExpressions;
namespace PhoneDemo
{
class Program
{
static void Main(string[] args)
{
string[] phones = { "13912345678", "15898765432", "12345678901", "19876543210", "17612345678" };
Regex reg = new Regex(@"^1[3-9]\d{9}#34;);
foreach (string phone in phones)
{
Console.WriteLine("{0} is {1}valid phone number.", phone, reg.IsMatch(phone) ? "" : "not ");
}
}
}
}
输出:
13912345678 is valid phone number.
15898765432 is valid phone number.
12345678901 is not valid phone number.
19876543210 is valid phone number.
17612345678 is valid phone number.
验证日期格式
日期格式的一般格式是:年-月-日,其中年可以是两位或四位数字,月和日可以是一位或两位数字,月的范围是1到12,日的范围根据月份和闰年的情况而定。一个可能的正则表达式是:
Regex reg = new Regex(@"^((\d{2}|\d{4})-(0?[1-9]|1[0-2])-(0?[1-9]|[12]\d|3[01]))#34;);
这个正则表达式的意思是:
- ^ : 匹配字符串的开头。
- (\d{2}|\d{4}) : 匹配两位或四位数字,表示年份,并捕获到第一个组中。
- : 匹配连字符。
- (0?[1-9]|1[0-2]) : 匹配一个可选的0和1到9中的任意一个数字,或者匹配10到12中的任意一个数字,表示月份,并捕获到第二个组中。
- : 匹配连字符。
- (0?[1-9]|[12]\d|3[01]) : 匹配一个可选的0和1到9中的任意一个数字,或者匹配10到29中的任意一个数字,或者匹配30或31,表示日期,并捕获到第三个组中。
- $ : 匹配字符串的结尾。
例如:
using System;
using System.Text.RegularExpressions;
namespace DateDemo
{
class Program
{
static void Main(string[] args)
{
string[] dates = { "2021-10-30", "21-8-15", "2020-02-29", "2021-13-01", "2021-02-30" };
Regex reg = new Regex(@"^((\d{2}|\d{4})-(0?[1-9]|1[0-2])-(0?[1-9]|[12]\d|3[01]))#34;);
foreach (string date in dates)
{
Console.WriteLine("{0} is {1}valid date format.", date, reg.IsMatch(date) ? "" : "not ");
}
}
}
}
输出:
2021-10-30 is valid date format.
21-8-15 is valid date format.
2020-02-29 is valid date format.
2021-13-01 is not valid date format.
2021-02-30 is not valid date format.
验证IP地址
IP地址的一般格式是:四个十进制数,每个数的范围是0到255,用点号分隔。一个可能的正则表达式是:
Regex reg = new Regex(@"^((0|[1-9]\d?|1\d\d|2[0-4]\d|25[0-5])\.){3}(0|[1-9]\d?|1\d\d|2[0-4]\d|25[0-5])#34;);
这个正则表达式的意思是:
- ^ : 匹配字符串的开头。
- (0|[1-9]\d?|1\d\d|2[0-4]\d|25[0-5]) : 匹配一个0,或者一个非零数字后面跟一个可选的数字,或者一个1后面跟两个数字,或者一个2后面跟一个0到4的数字和任意数字,或者一个25后面跟一个0到5的数字,表示一个十进制数,并捕获到第一个组中。
- . : 匹配点号。
- {3} : 表示重复前面的组三次。
- (0|[1-9]\d?|1\d\d|2[0-4]\d|25[0-5]) : 同上,表示最后一个十进制数,并捕获到第二个组中。
- $ : 匹配字符串的结尾。
例如:
using System;
using System.Text.RegularExpressions;
namespace IPDemo
{
class Program
{
static void Main(string[] args)
{
string[] ips = { "192.168.1.1", "255.255.255.255", "10.10.10.10", "256.256.256.256", "192.168.-1.-1" };
Regex reg = new Regex(@"^((0|[1-9]\d?|1\d\d|2[0-4]\d|25[0-5])\.){3}(0|[1-9]\d?|1\d\d|2[0-4]\d|25[0-5])#34;);
foreach (string ip in ips)
{
Console.WriteLine("{0} is {1}valid IP address.", ip, reg.IsMatch(ip) ? "" : "not ");
}
}
}
}
输出:
192.168.1.1 is valid IP address.
255.255.255.255 is valid IP address.
10.10.10.10 is valid IP address.
256.256.256.256 is not valid IP address.
192.168.-1.-1 is not valid IP address.
总结
本文介绍了如何使用C#编写正则表达式来验证不同的格式,如手机号码、日期和IP地址。正则表达式是一种强大的工具,可以用来匹配、提取和替换文本中的特定模式。本文给出了一些常用的正则表达式模式的示例和解释,以及如何在C#中使用Regex类来应用这些模式。正则表达式的语法和功能很丰富,有很多细节和技巧需要掌握,因此建议读者进一步学习和练习正则表达式的使用。
本文的目的是帮助读者了解正则表达式在C#中的基本用法和应用场景,以及如何编写有效的正则表达式模式。希望本文能对读者有所帮助,也欢迎读者在评论区留下自己的问题和建议。