正则表达式用实际字符替换所有 ASCII 字符代码
Regex replacing all ASCII character codes with actual characters
我有一个看起来像这样的字符串:
4000 BCE–5000 BCE and 600 CE–650 CE
.
我正在尝试使用正则表达式搜索字符串,找到所有字符代码并将所有字符代码替换为相应的实际字符。对于我的示例字符串,我希望得到一个看起来像
的字符串
4000 BCE–5000 BCE and 600 CE–650 CE
.
我试过用代码写,但我不知道该写什么:
string line = "4000 BCE–5000 BCE and 600 CE–650 CE";
listof?datatype matches = search through `line` and find all the matches to "&#.*?;"
foreach (?datatype match in matches){
int extractedNumber = Convert.ToInt32(Regex.(/*extract the number that is between the &# and the ?*/));
//convert the number to ascii character
string actualCharacter = (char) extractedNumber + "";
//replace character code in original line
line = Regex.Replace(line, match, actualCharacter);
}
编辑
我的原始字符串实际上有一些 HTML 并且看起来像:
4000 <small>BCE</small>–5000 <small>BCE</small> and 600 <small>CE</small>–650 <small>CE</small>
我使用 line = Regex.Replace(note, "<.*?>", string.Empty);
删除了 <small>
标签,但显然,根据 SO 上最流行的问题之一,RegEx match open tags except XHTML self-contained tags,你真的不应该使用 RegEx 删除HTML.
如何在代表替换中做到这一点。
编辑:作为旁注,这是一个很好的正则表达式,可以删除所有标签和脚本块
<(?:script(?:\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+)?\s*>[\S\s]*?</script\s*|(?:/?[\w:]+\s*/?)|(?:[\w:]+\s+(?:(?:(?:"[\S\s]*?")|(?:'[\S\s]*?'))|(?:[^>]*?))+\s*/?)|\?[\S\s]*?\?|(?:!(?:(?:DOCTYPE[\S\s]*?)|(?:\[CDATA\[[\S\s]*?\]\])|(?:--[\S\s]*?--)|(?:ATTLIST[\S\s]*?)|(?:ENTITY[\S\s]*?)|(?:ELEMENT[\S\s]*?))))>
C#:
string line = @"4000 BCE–5000 BCE and 600 CE–650 CE";
Regex RxCode = new Regex(@"&#([0-9]+);");
string lineNew = RxCode.Replace(
line,
delegate( Match match ) {
return "" + (char)Convert.ToInt32( match.Groups[1].Value);
}
);
Console.WriteLine( lineNew );
输出:
4000 BCE-5000 BCE and 600 CE-650 CE
edit: 如果您也期望 hex 形式,您也可以处理。
# @"&\#(?:([0-9]+)|x([0-9a-fA-F]+));"
&\#
(?:
( [0-9]+ ) # (1)
| x
( [0-9a-fA-F]+ ) # (2)
)
;
C#:
Regex RxCode = new Regex(@"&#(?:([0-9]+)|x([0-9a-fA-F]+));");
string lineNew = RxCode.Replace(
line,
delegate( Match match ) {
return match.Groups[1].Success ?
"" + (char)Convert.ToInt32( match.Groups[1].Value ) :
"" + (char)Int32.Parse( match.Groups[2].Value, System.Globalization.NumberStyles.HexNumber);
}
);
您不需要任何正则表达式即可将 XML 实体引用转换为文字字符串。
解决方案 1:XML-有效输入
这是假设您有 XML 有效输入的解决方案。
添加 using System.Xml;
命名空间并使用此方法:
public string XmlUnescape(string escaped)
{
XmlDocument doc = new XmlDocument();
XmlNode node = doc.CreateElement("root");
node.InnerXml = escaped;
return node.InnerText;
}
这样使用:
var output1 = XmlUnescape("4000 BCE–5000 BCE and 600 CE–650 CE.");
结果:
解决方案 2:具有 HTML/XML 个实体的无效 XML 输入
如果您不能将 XmlDocument
与您的字符串一起使用,因为它们包含无效的 XML 语法,您可以使用以下方法,该方法使用 HttpUtility.HtmlDecode
仅转换为已知 HTML 和 XML 个实体:
public string RevertEntities(string test)
{
Regex rxHttpEntity = new Regex(@"(&[#\w]+;)"); // Declare a regex (better initialize it as a property/field of a static class for better performance
string last_res = string.Empty; // a temporary variable holding a previously found entity
while (rxHttpEntity.IsMatch(test)) // if our input has something like e or
{
test = test.Replace(rxHttpEntity.Match(test).Value, HttpUtility.HtmlDecode(rxHttpEntity.Match(test).Value.ToLower())); // Replace all the entity references with there literal value (& => &)
if (last_res == test) // Check if we made any change to the string
break; // If not, stop processing (there are some unsupported entities like &ourgreatcompany;
else
last_res = test; // Else, go on checking for entities
}
return test;
}
调用如下:
var output2 = RevertEntities("4000 BCE–5000 BCE and 600 CE–650 CE.");
解决方案 3:HtmlAgilityPack 和 HtmlEntity.DeEntitize
使用 Manage NuGet Packages for Solution 下载并安装 HtmlAgilityPack 并使用此代码获取所有文本:
public string getCleanHtml(string html)
{
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
return HtmlAgilityPack.HtmlEntity.DeEntitize(doc.DocumentNode.InnerText);
}
然后使用
var txt = "4000 <small>BCE</small>–5000 <small>BCE</small> and 600 <small>CE</small>–650 <small>CE</small>";
var clean = getCleanHtml(txt);
结果:
doc.DocumentNode.InnerText.Substring(doc.DocumentNode.InnerText.IndexOf("\n")).Trim();
您可以将 LINQ 与 HtmlAgilityPack 一起使用,下载页面(使用 var webGet = new HtmlAgilityPack.HtmlWeb(); var doc = webGet.Load(url);
),等等。最好的是没有实体需要手动处理。
我有一个看起来像这样的字符串:
4000 BCE–5000 BCE and 600 CE–650 CE
.
我正在尝试使用正则表达式搜索字符串,找到所有字符代码并将所有字符代码替换为相应的实际字符。对于我的示例字符串,我希望得到一个看起来像
的字符串
4000 BCE–5000 BCE and 600 CE–650 CE
.
我试过用代码写,但我不知道该写什么:
string line = "4000 BCE–5000 BCE and 600 CE–650 CE";
listof?datatype matches = search through `line` and find all the matches to "&#.*?;"
foreach (?datatype match in matches){
int extractedNumber = Convert.ToInt32(Regex.(/*extract the number that is between the &# and the ?*/));
//convert the number to ascii character
string actualCharacter = (char) extractedNumber + "";
//replace character code in original line
line = Regex.Replace(line, match, actualCharacter);
}
编辑
我的原始字符串实际上有一些 HTML 并且看起来像:
4000 <small>BCE</small>–5000 <small>BCE</small> and 600 <small>CE</small>–650 <small>CE</small>
我使用 line = Regex.Replace(note, "<.*?>", string.Empty);
删除了 <small>
标签,但显然,根据 SO 上最流行的问题之一,RegEx match open tags except XHTML self-contained tags,你真的不应该使用 RegEx 删除HTML.
如何在代表替换中做到这一点。
编辑:作为旁注,这是一个很好的正则表达式,可以删除所有标签和脚本块
<(?:script(?:\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+)?\s*>[\S\s]*?</script\s*|(?:/?[\w:]+\s*/?)|(?:[\w:]+\s+(?:(?:(?:"[\S\s]*?")|(?:'[\S\s]*?'))|(?:[^>]*?))+\s*/?)|\?[\S\s]*?\?|(?:!(?:(?:DOCTYPE[\S\s]*?)|(?:\[CDATA\[[\S\s]*?\]\])|(?:--[\S\s]*?--)|(?:ATTLIST[\S\s]*?)|(?:ENTITY[\S\s]*?)|(?:ELEMENT[\S\s]*?))))>
C#:
string line = @"4000 BCE–5000 BCE and 600 CE–650 CE";
Regex RxCode = new Regex(@"&#([0-9]+);");
string lineNew = RxCode.Replace(
line,
delegate( Match match ) {
return "" + (char)Convert.ToInt32( match.Groups[1].Value);
}
);
Console.WriteLine( lineNew );
输出:
4000 BCE-5000 BCE and 600 CE-650 CE
edit: 如果您也期望 hex 形式,您也可以处理。
# @"&\#(?:([0-9]+)|x([0-9a-fA-F]+));"
&\#
(?:
( [0-9]+ ) # (1)
| x
( [0-9a-fA-F]+ ) # (2)
)
;
C#:
Regex RxCode = new Regex(@"&#(?:([0-9]+)|x([0-9a-fA-F]+));");
string lineNew = RxCode.Replace(
line,
delegate( Match match ) {
return match.Groups[1].Success ?
"" + (char)Convert.ToInt32( match.Groups[1].Value ) :
"" + (char)Int32.Parse( match.Groups[2].Value, System.Globalization.NumberStyles.HexNumber);
}
);
您不需要任何正则表达式即可将 XML 实体引用转换为文字字符串。
解决方案 1:XML-有效输入
这是假设您有 XML 有效输入的解决方案。
添加 using System.Xml;
命名空间并使用此方法:
public string XmlUnescape(string escaped)
{
XmlDocument doc = new XmlDocument();
XmlNode node = doc.CreateElement("root");
node.InnerXml = escaped;
return node.InnerText;
}
这样使用:
var output1 = XmlUnescape("4000 BCE–5000 BCE and 600 CE–650 CE.");
结果:
解决方案 2:具有 HTML/XML 个实体的无效 XML 输入
如果您不能将 XmlDocument
与您的字符串一起使用,因为它们包含无效的 XML 语法,您可以使用以下方法,该方法使用 HttpUtility.HtmlDecode
仅转换为已知 HTML 和 XML 个实体:
public string RevertEntities(string test)
{
Regex rxHttpEntity = new Regex(@"(&[#\w]+;)"); // Declare a regex (better initialize it as a property/field of a static class for better performance
string last_res = string.Empty; // a temporary variable holding a previously found entity
while (rxHttpEntity.IsMatch(test)) // if our input has something like e or
{
test = test.Replace(rxHttpEntity.Match(test).Value, HttpUtility.HtmlDecode(rxHttpEntity.Match(test).Value.ToLower())); // Replace all the entity references with there literal value (& => &)
if (last_res == test) // Check if we made any change to the string
break; // If not, stop processing (there are some unsupported entities like &ourgreatcompany;
else
last_res = test; // Else, go on checking for entities
}
return test;
}
调用如下:
var output2 = RevertEntities("4000 BCE–5000 BCE and 600 CE–650 CE.");
解决方案 3:HtmlAgilityPack 和 HtmlEntity.DeEntitize
使用 Manage NuGet Packages for Solution 下载并安装 HtmlAgilityPack 并使用此代码获取所有文本:
public string getCleanHtml(string html)
{
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
return HtmlAgilityPack.HtmlEntity.DeEntitize(doc.DocumentNode.InnerText);
}
然后使用
var txt = "4000 <small>BCE</small>–5000 <small>BCE</small> and 600 <small>CE</small>–650 <small>CE</small>";
var clean = getCleanHtml(txt);
结果:
您可以将 LINQ 与 HtmlAgilityPack 一起使用,下载页面(使用 var webGet = new HtmlAgilityPack.HtmlWeb(); var doc = webGet.Load(url);
),等等。最好的是没有实体需要手动处理。