前言

Replace 的作用就是,通过指定内容的替换,返回一个新字符串。

返回值中,已将当前字符串中的指定 Unicode 字符或 String 的 所有匹配项,替换为指定的新的 Unicode 字符或 String。

一、String.Replace() 的几个重载

String.Replace() 总共有四个重载,分别是:(详见官网:String.Replace 方法

  Replace(Char, Char)、

  Replace(String, String)、

  Replace(String, String, StringComparison)、

  Replace(String, String, Boolean, CultureInfo)。

下面来逐个简单介绍下。

1、Replace(Char, Char)

// 作用:
// 将实例中出现的所有指定 Unicode 字符都替换为另一个指定的 Unicode 字符。
// 语法:
public string Replace (char oldChar, char newChar);

代码示例:

String str = "1 2 3 4 5 6 7 8 9";
Console.WriteLine($"Original string: {str}");
Console.WriteLine($"CSV string: {str.Replace(' ', ',')}");
// 输出结果:
// Original string: "1 2 3 4 5 6 7 8 9"
// CSV string: "1,2,3,4,5,6,7,8,9"

现在补充一下关于 Char 类型:

  char 类型关键字是 .NET System.Char 结构类型的别名,它表示 Unicode UTF-16 字符。

类型 范围 大小 .NET 类型 默认值
char U+0000 到 U+FFFF 16 位 System.Char \0 即 U+0000
// 给 Char 类型的变量赋值可以通过多重方式,如下:
var chars = new[]
{
'j', //字符文本
'\u006A', //Unicode 转义序列,它是 \u 后跟字符代码的十六进制表示形式(四个符号)
'\x006A', //十六进制转义序列,它是 \x 后跟字符代码的十六进制表示形式
(char)106, //将字符代码的值转换为相应的 char 值
};
Console.WriteLine(string.Join(" ", chars));
// 输出的值相同: j j j j

  char 类型可隐式转换为以下整型类型:ushort、int、uint、long 和 ulong。

  也可以隐式转换为内置浮点数值类型:float、double 和 decimal。

  可以显式转换为 sbyte、byte 和 short 整型类型。

2、String.Replace(String, String)

// 作用:
// 实例中出现的所有指定字符串都替换为另一个指定的字符串
// 语法:
public string Replace (char oldString, char newString);

示例:

// 目的:将错误的单词更正
string errString = "This docment uses 3 other docments to docment the docmentation";
Console.WriteLine($"The original string is:{Environment.NewLine}'{errString}'{Environment.NewLine}");
// 正确的拼写应该为 "document"
string correctString = errString.Replace("docment", "document");
Console.WriteLine($"After correcting the string, the result is:{Environment.NewLine}'{correctString}'");
// 输出结果:
// The original string is:
// 'This docment uses 3 other docments to docment the docmentation'
//
// After correcting the string, the result is:
// 'This document uses 3 other documents to document the documentation'
//

另一个示例:

// 可进行连续多次替换操作
String s = "aaa";
Console.WriteLine($"The initial string: '{s}'");
s = s.Replace("a", "b").Replace("b", "c").Replace("c", "d");
Console.WriteLine($"The final string: '{s}'");
// 如果 newString 为 null,则将 oldString 的匹配项全部删掉
s = s.Replace("dd", null);
Console.WriteLine($"The new string: '{s}'"); // 输出结果:
//The initial string: 'aaa'
//The final string: 'ddd'
//The new string: 'd'

3、Replace(String, String, StringComparison)

相较于上一个重载,新增了一个入参枚举类型 StringComparison(详见官网:StringComparison 枚举)。作用是:指定供 Compare(String, String) 和 Equals(Object) 方法的特定重载,使用的区域性、大小写和排序规则。

相关源代码如下,可以看出,不同的 StringComparison 参数值对应的操作不同,最主要的区别就是是否添加参数 CultureInfo。

public string Replace(string oldValue, string? newValue, StringComparison comparisonType)
{
switch (comparisonType)
{
case StringComparison.CurrentCulture:
case StringComparison.CurrentCultureIgnoreCase:
return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture.CompareInfo,
GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.InvariantCulture:
case StringComparison.InvariantCultureIgnoreCase:
return ReplaceCore(oldValue, newValue, CompareInfo.Invariant,
GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.Ordinal:
return Replace(oldValue, newValue);
case StringComparison.OrdinalIgnoreCase:
return ReplaceCore(oldValue, newValue, CompareInfo.Invariant, CompareOptions.OrdinalIgnoreCase);
default:
throw new ArgumentException(SR.NotSupported_StringComparison, "comparisonType");
}
}

关于不同区域的不同 CultureInfo 实例,程序运行结果的区别,见下面的示例:

查看代码
// 以下示例为三种语言("zh-CN", "th-TH", "tr-TR")不同枚举值的测试代码和输出结果:
String[] cultureNames = { "zh-CN", "th-TH", "tr-TR" }; // 中国 泰国 土耳其
String[] strings1 = { "a", "i", "case", };
String[] strings2 = { "a-", "\u0130", "Case" };
StringComparison[] comparisons = (StringComparison[])Enum.GetValues(typeof(StringComparison));
foreach (var cultureName in cultureNames)
{
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
Console.WriteLine("Current Culture: {0}", CultureInfo.CurrentCulture.Name);
for (int ctr = 0; ctr <= strings1.GetUpperBound(0); ctr++)
{
foreach (var comparison in comparisons)
Console.WriteLine(" {0} = {1} ({2}): {3}", strings1[ctr], strings2[ctr], comparison,
String.Equals(strings1[ctr], strings2[ctr], comparison));
Console.WriteLine();
}
Console.WriteLine();
} // 输出结果:
// Current Culture: zh-CN
// a = a- (CurrentCulture): False //-----注意------
// a = a- (CurrentCultureIgnoreCase): False //-----注意------
// a = a- (InvariantCulture): False
// a = a- (InvariantCultureIgnoreCase): False
// a = a- (Ordinal): False
// a = a- (OrdinalIgnoreCase): False
//
// i = İ (CurrentCulture): False
// i = İ (CurrentCultureIgnoreCase): False //-----注意------
// i = İ (InvariantCulture): False
// i = İ (InvariantCultureIgnoreCase): False
// i = İ (Ordinal): False
// i = İ (OrdinalIgnoreCase): False
//
// case = Case (CurrentCulture): False
// case = Case (CurrentCultureIgnoreCase): True
// case = Case (InvariantCulture): False
// case = Case (InvariantCultureIgnoreCase): True
// case = Case (Ordinal): False
// case = Case (OrdinalIgnoreCase): True
//
//
// Current Culture: th-TH
// a = a- (CurrentCulture): True //-----注意------
// a = a- (CurrentCultureIgnoreCase): True //-----注意------
// a = a- (InvariantCulture): False
// a = a- (InvariantCultureIgnoreCase): False
// a = a- (Ordinal): False
// a = a- (OrdinalIgnoreCase): False
//
// i = İ (CurrentCulture): False
// i = İ (CurrentCultureIgnoreCase): False
// i = İ (InvariantCulture): False
// i = İ (InvariantCultureIgnoreCase): False
// i = İ (Ordinal): False
// i = İ (OrdinalIgnoreCase): False
//
// case = Case (CurrentCulture): False
// case = Case (CurrentCultureIgnoreCase): True
// case = Case (InvariantCulture): False
// case = Case (InvariantCultureIgnoreCase): True
// case = Case (Ordinal): False
// case = Case (OrdinalIgnoreCase): True
//
//
// Current Culture: tr-TR
// a = a- (CurrentCulture): False
// a = a- (CurrentCultureIgnoreCase): False
// a = a- (InvariantCulture): False
// a = a- (InvariantCultureIgnoreCase): False
// a = a- (Ordinal): False
// a = a- (OrdinalIgnoreCase): False
//
// i = İ (CurrentCulture): False
// i = İ (CurrentCultureIgnoreCase): True //-----注意------
// i = İ (InvariantCulture): False
// i = İ (InvariantCultureIgnoreCase): False
// i = İ (Ordinal): False
// i = İ (OrdinalIgnoreCase): False
//
// case = Case (CurrentCulture): False
// case = Case (CurrentCultureIgnoreCase): True
// case = Case (InvariantCulture): False
// case = Case (InvariantCultureIgnoreCase): True
// case = Case (Ordinal): False
// case = Case (OrdinalIgnoreCase): True

4、Replace(String, String, Boolean, CultureInfo)

此重载主要介绍下后两个入参。

Boolean:布尔类型入参,默认 false。true:忽略大小写;false:区分大小写。

CultureInfo:指定代码的区域性,允许为 null,但必须站位。为空时当前区域(CultureInfo.CurrentCulture.CompareInfo)。

注:关于 CultureInfo 的详细测试示例,详见上一部分中的折叠代码。

以下是当前重载的部分源码:

查看代码
 public string Replace(string oldValue, string? newValue, bool ignoreCase, CultureInfo? culture)
{
return ReplaceCore(oldValue, newValue, culture?.CompareInfo, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
}
private string ReplaceCore(string oldValue, string newValue, CompareInfo ci, CompareOptions options)
{
if ((object)oldValue == null)
{
throw new ArgumentNullException("oldValue");
}
if (oldValue.Length == 0)
{
throw new ArgumentException(SR.Argument_StringZeroLength, "oldValue");
}
return ReplaceCore(this, oldValue.AsSpan(), newValue.AsSpan(), ci ?? CultureInfo.CurrentCulture.CompareInfo, options) ?? this;
}
private static string ReplaceCore(ReadOnlySpan<char> searchSpace, ReadOnlySpan<char> oldValue, ReadOnlySpan<char> newValue, CompareInfo compareInfo, CompareOptions options)
{
Span<char> initialBuffer = stackalloc char[256];
ValueStringBuilder valueStringBuilder = new ValueStringBuilder(initialBuffer);
valueStringBuilder.EnsureCapacity(searchSpace.Length);
bool flag = false;
while (true)
{
int matchLength;
int num = compareInfo.IndexOf(searchSpace, oldValue, options, out matchLength);
if (num < 0 || matchLength == 0)
{
break;
}
valueStringBuilder.Append(searchSpace.Slice(0, num));
valueStringBuilder.Append(newValue);
searchSpace = searchSpace.Slice(num + matchLength);
flag = true;
}
if (!flag)
{
valueStringBuilder.Dispose();
return null;
}
valueStringBuilder.Append(searchSpace);
return valueStringBuilder.ToString();
}

二、Regex.Replace() 的几个常用重载

1、Replace(String, String)

在指定的输入字符串(input)内,使用指定的替换字符串(replacement),替换与某个正则表达式模式(需要在实例化 Regex 对象时,将正则表达式传入)匹配的所有的字符串。

// 语法
public string Replace (string input, string replacement);

下面是一个简单的示例:

// 目的是将多余的空格去掉
string input = "This is text with far too much white space.";
string pattern = "\\s+"; // \s:匹配任何空白字符;+:匹配一次或多次
string replacement = " ";
Regex rgx = new Regex(pattern); // 实例化时传入正则表达式
string result = rgx.Replace(input, replacement);
Console.WriteLine("Original String: {0}", input);
Console.WriteLine("Replacement String: {0}", result);
// 输出结果:
// Original String: This is text with far too much white space.
// Replacement String: This is text with far too much white space.

2、Replace(String, String, String)

在指定的输入字符串内(input),使用指定的替换字符串(replacement)替换与指定正则表达式(pattern)匹配的所有字符串。

// 语法:
public static string Replace (string input, string pattern, string replacement);
// 目的:将多余的空格去掉
string input = "This is text with far too much white space.";
string pattern = "\\s+";
// 注:\s 匹配任何空白字符,包括空格、制表符、换页符等
// 注:+ 重复一次或多次
string replacement = " "; // 将连续出现的多个空格,替换为一个
string result = Regex.Replace(input, pattern, replacement);
Console.WriteLine("Original String: {0}", input);
Console.WriteLine("Replacement String: {0}", result);
// 输出结果:
//Original String: This is text with far too much white space.
//Replacement String: This is text with far too much white space.

3、Replace(String, String, Int32, Int32)

在指定输入子字符串(input)内,使用指定替换字符串(replacement)替换与某个正则表达式模式匹配的字符串(其数目为指定的最大数目)。startat 是匹配开始的位置。

// 语法:
public string Replace (string input, string replacement, int count, int startat);

下面是一个示例:

// 目的:添加双倍行距
string input = "Instantiating a New Type\n" +
"Generally, there are two ways that an\n" +
"instance of a class or structure can\n" +
"be instantiated. ";
Console.WriteLine("原内容:");
Console.WriteLine(input);
// .:匹配除‘\n’之外的任何单个字符;*:匹配零次或多次
string pattern = "^.*$"; // ^.*$ 在这里就是匹配每一行中‘\n’前边的字符串
string replacement = "\n$&"; // 在匹配项前添加‘\n’;$&:代表匹配内容
Regex rgx = new Regex(pattern, RegexOptions.Multiline); // Multiline:多行模式,不仅仅在整个字符串的开头和结尾匹配
string result = string.Empty;
Match match = rgx.Match(input); // 判断能否匹配
if (match.Success)
result = rgx.Replace(input,
replacement,
-1, // >= 0 时,就是匹配具体次数,= -1 时就是不限制次数
match.Index + match.Length + 1 // 作用就是跳过第一个匹配项(第一行不做处理)
// 当第一次匹配时:Index=0,length=除了‘\n’之外的长度,最后再 +1 就是第一行全部的内容
);
Console.WriteLine("结果内容:");
Console.WriteLine(result);
// 输出结果:
// 原内容:
// Instantiating a New Type
// Generally, there are two ways that an
// instance of a class or structure can
// be instantiated.
// 结果内容:
// Instantiating a New Type
//
// Generally, there are two ways that an
//
// instance of a class or structure can
//
// be instantiated.

4、Replace(String, String, MatchEvaluator, RegexOptions, TimeSpan)

在入参字符串(input)中,进行正则表达式(pattern)的匹配,匹配成功的,传递给 MatchEvaluator 委托(evaluator)处理完成后,替换原匹配值。

RegexOptions 为匹配操作配置项(关于 RegexOptions 详见官网:RegexOptions 枚举),TimeSpan 为超时时间间隔。

public static string Replace (string input, string pattern,
System.Text.RegularExpressions.MatchEvaluator evaluator,
System.Text.RegularExpressions.RegexOptions options,
TimeSpan matchTimeout);

下面是一个示例:

// 目的:将输入的每个单词中的字母顺序随机打乱,再一起输出
static void Main(string[] args)
{
string words = "letter alphabetical missing lack release " +
"penchant slack acryllic laundry cease";
string pattern = @"\w+ # Matches all the characters in a word.";
MatchEvaluator evaluator = new MatchEvaluator(WordScrambler); // WordScrambler:回调函数
Console.WriteLine("Original words:");
Console.WriteLine(words);
Console.WriteLine();
try
{
Console.WriteLine("Scrambled words:");
Console.WriteLine(Regex.Replace(words, pattern, evaluator,
RegexOptions.IgnorePatternWhitespace, TimeSpan.FromSeconds(2)));
}
catch (RegexMatchTimeoutException)
{
Console.WriteLine("Word Scramble operation timed out.");
Console.WriteLine("Returned words:");
}
}
/// <summary>
/// 回调:对全部匹配项逐一进行操作
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public static string WordScrambler(Match match)
{
int arraySize = match.Value.Length;
double[] keys = new double[arraySize]; // 存放随机数
char[] letters = new char[arraySize]; // 存放字母
Random rnd = new Random();
for (int ctr = 0; ctr < match.Value.Length; ctr++)
{
keys[ctr] = rnd.NextDouble(); // 生成随机数,用于重新排序
letters[ctr] = match.Value[ctr]; // 将输入参单词数拆解为字母数组
}
Array.Sort(keys, letters, 0, arraySize, Comparer.Default); // 重新根据随机数大小排序
return new String(letters);
}
// 输出结果:
// Original words:
// letter alphabetical missing lack release penchant slack acryllic laundry cease
//
// Scrambled words:
// eltetr aeplbtaiaclh ignisms lkac elsaree nchetapn acksl lcyaricl udarnly casee

三、关于 Replace 的实际需求简单示例

1、全部替换匹配项

string input = "Instantiating Instantiating Instantiating Instantiating";
Console.WriteLine("----原内容----");
Console.WriteLine(input);
string result = input.Replace("tiating","*******");
Console.WriteLine("----结果内容----");
Console.WriteLine(result);
// ----原内容----
// Instantiating Instantiating Instantiating Instantiating
// ----结果内容----
// Instan******* Instan******* Instan******* Instan*******

2、仅替换第一个匹配项

string input = "Instantiating Instantiating Instantiating Instantiating";
Console.WriteLine("----原内容----");
Console.WriteLine(input);
Regex regex = new Regex("tiating");
string result = regex.Replace(input, "*******",1);
Console.WriteLine("----结果内容----");
Console.WriteLine(result);
// ----原内容----
// Instantiating Instantiating Instantiating Instantiating
// ----结果内容----
// Instan******* Instantiating Instantiating Instantiating

3、仅替换最后一个匹配项

string input = "Instantiating Instantiating Instantiating Instantiating";
Console.WriteLine("----原内容----");
Console.WriteLine(input);
Match match = Regex.Match(input, "tiating",RegexOptions.RightToLeft);
string first = input.Substring(0, match.Index);
string last = input.Length == first.Length + match.Length ? "" :
input.Substring(first.Length + match.Length,input.Length-(first.Length + match.Length));
string result = $"{first}*******{last}";
Console.WriteLine("----结果内容----");
Console.WriteLine(result);
// 两次测试结果:
// ----原内容----
// Instantiating Instantiating Instantiating Instantiating 345
// ----结果内容----
// Instantiating Instantiating Instantiating Instan******* 345
// ----原内容----
// Instantiating Instantiating Instantiating Instantiating
// ----结果内容----
// Instantiating Instantiating Instantiating Instan*******

参考:String.Replace 方法

     Regex.Replace 方法

注:如有建议或疑问,欢迎留言。

C# Replace:一个熟悉而又陌生的替换的更多相关文章

  1. 剑指offer 1,输入一个字符串,将字符串的空格替换成%20

    剑指offer 1,输入一个字符串,将字符串的空格替换成%20    function replaceSpace(str){      return str.replace(/\s/g,"% ...

  2. Android探索之ContentProvider熟悉而又陌生的组件

    前言: 总结这篇文章之前我们先来回顾一下Android Sqlite数据库,参考文章:http://www.cnblogs.com/whoislcj/p/5506294.html,Android程序内 ...

  3. CLR via C#(15)--String,熟悉而又陌生

    好久没写文章了,再拿起这本书,学习加分享,乐趣无穷啊.这两天看了写关于字符串的知识,从学写代码的时候开始,我们就基本天天跟String打交道,对它再熟悉不过了.但是仔细看看,还是有一种拨开云雾的感觉, ...

  4. 《程序员的呐喊》:一个熟悉多种语言的老程序员对编程语言、开发流程、google的战略等的思考,比较有趣。 五星推荐

    作者熟悉二三十种编程语言,写了20多年代码.本书是作者对编程语言.开发流程.google的战略等的思考.比较有趣. 前面部分是作者对编程语言的一些思考.作者鄙视C++, Java,面向对象.比较有趣的 ...

  5. 分享一个正则对html标签的替换

    replace_html(parm){ let self = this; return self.trim(parm.replace(new RegExp("<[^<]*> ...

  6. sql把一个字段中的特定字符替换成其他字符

    将'0654879'替换成'0754879' UPDATE dbo.SG_Functionality SET FunctionalityCode=REPLACE(FunctionalityCode,' ...

  7. Android Studio环境下搭建ReactNative

    1.安装Android Studio首先肯定是 安装Android Studio(包含SDK)(国内推荐)ps:这里有一点要注意,需要为SDK配置环境变量,名称必须为ANDROID_HOME 2.安装 ...

  8. 转:MSN君最后的十个瞬间

    五年前我用过MSN五年.在一家ERP公司当程序猿的时候我甚至在业余时间做过一款MSN订餐机器人. 转完这篇文章.就是真正跟MSN的bye bye了. 转自:www.gogo.cn 今天是一个普通的周五 ...

  9. ASP.NET进行请求转发

    前言 前两天将网站的部分功能在小程序上实现,网站的后台是http,没有配置域名和安全证书,小程序的线上版本是无法访问的,因此需要从配有域名和安全证书的站点进行转发.即小程序请求A,A转发请求到B,B获 ...

  10. C++ 知识零碎搭建

    全局变量 局部变量 函数不能嵌套定义 C/C++ 变量在将要被使用时定义即可, 不必一开始就声明所有变量 函数的定义与声明的区别 C++常规类型自动类型转换规则 C语言中十六进制和八进制的格式: 二进 ...

随机推荐

  1. Centos7.6分区、格式化、自动挂载磁盘

    个人名片: 对人间的热爱与歌颂,可抵岁月冗长 Github‍:念舒_C.ying CSDN主页️:念舒_C.ying 个人博客 :念舒_C.ying 目录 1. 添加硬盘 2. 执行fdisk -l ...

  2. dp状态设计

    迎接仪式 题目描述 LHX 教主要来 X 市指导 OI 学习工作了.为了迎接教主,在一条道路旁,一群"Orz 教主 er"穿着文化衫站在道路两旁迎接教主,每件文化衫上都印着大字.一 ...

  3. mysql不需要密码,乱输入密码就能进去。。。。解决

    为什么MySQL 不用输入用户名和密码也能访问 今天后天连接数据库时密码写错了,却发现后台能够拿到数据库中的数据,又故意把用户名和密码都写错,结果还是可以.这就意味着任何一个人只要登入服务器,就可以轻 ...

  4. elasticsearch 聚合之 date_histogram 聚合

    目录 1.背景 2.bucket_key如何计算 3.前置知识 4.日历和固定时间间隔 4.1 Calendar intervals 日历间隔 4.2 Fixed intervals 固定间隔 5.数 ...

  5. Blazor和Vue对比学习(进阶.路由导航一):基本使用

    Blazor和Vue都是单文件组件SPA,路由的实现逻辑非常相似,页面路径的改变都是组件的切换,但因为各自语言的特性,在实现方式上有较大差异. 一.安装 1.Vue:Router是Vue的一个插件.如 ...

  6. Hadoop安装-分布式-Fully

    Hadoop安装-分布式-Fully 〇.所需资料 一.配置 1.基础配置 (1)系统安装 (2)hostname主机名配置 (3)ip地址.dns.hosts映射文件配置 (4)关闭防火墙与seli ...

  7. C++日期和时间编程总结

    一,概述 二,C-style 日期和时间库 2.1,数据类型 2.2,函数 2.3,数据类型与函数关系梳理 2.4,时间类型 2.4.1,UTC 时间 2.4.2,本地时间 2.4.3,纪元时间 2. ...

  8. TS编写发布订阅模式

    interface PubSubType { events: { [key: string]: { name: string, once: boolean, cb: Function }[] } on ...

  9. 过滤器 Filter 与 拦截器 Interceptor 的区别

    引言 说起 Filter 与 Interceptor 的区别,相信很多同学第一感觉就是容易.简单! 毕竟开发中这两个组件使用频率较高,用法也较简单.然后真回答起来有答不出个所以然来,场面尴尬,老丢脸了 ...

  10. 2、postman调试

    Postman接口调试: postman博客参考 Postman是一个API(接口)开发协作平台,其提供了发送请求.检查响应.自动化测试.数据模拟.服务监控.文档分享等一系列与API(接口)开发有关的 ...