在字符串中查找各种数字
本文关键字:数字 查找 字符串 | 更新日期: 2023-09-27 18:35:31
,字符串可以包含整数,浮点数和十六进制数。
"这个字符串可以有 -345 和 57,也可以有 35.4656 或微妙的0xF46434等等"
我可以使用什么来在 C# 中查找这些数字?
使用以下行的内容:(我自己写的,所以我不会说它对于您要查找的任何类型的数字都是包罗万象的,但它适用于您的示例)
var str = "123 This a string than can have -345 and 57 and could also have 35.4656 or a subtle 0XF46434 and more like -0xf46434";
var a = Regex.Matches(str, @"(?<=(^|[^a-zA-Z0-9_^]))(-?'d+('.'d+)?|-?0[xX][0-9A-Fa-f]+)(?=([^a-zA-Z0-9_]|$))");
foreach (Match match in a)
{
//do something
}
正则表达式似乎是一种只写语言(即难以阅读),所以我会分解它,以便你理解:(?<=(^|[^a-zA-Z0-9_^]))
是一个通过单词边界打破它的回望。 我不能使用'b
,因为它认为-
是边界字符,所以它只会匹配345
而不是-345
。 -?'d+('.'d+)?
匹配十进制数字(可选为负数),也可以匹配小数。 -?0[xX][0-9A-Fa-f]+
匹配十六进制数字,不区分大小写,可选为负数。 最后,(?=([^a-zA-Z0-9_]|$))
是展望,再次作为单词边界。 请注意,在第一个边界中,我允许字符串的开头,这里我允许字符串的结尾。
只需尝试解析每个单词以double
并return
double
s的array
。
这是一种从string
中获取double
array
的方法:
double[] GetNumbers(string str)
{
double num;
List<double> l = new List<double>();
foreach (string s in str.Split(' '))
{
bool isNum = double.TryParse(s, out num);
if (isNum)
{
l.Add(num);
}
}
return l.ToArray();
}
有关double.TryParse()
的更多信息,请点击此处。
鉴于您在上面的输入,此表达式匹配那里存在的每个数字
string line = "This a string than can have " +
"-345 and 57 and could also have 35.4656 " +
"or a subtle 0xF46434 and more";
Regex r = new Regex(@"(-?0[Xx][A-Fa-f0-9]+|-?'d+'.'d+|-?'d+)");
var m = r.Matches(line);
foreach(Match h in m)
Console.WriteLine(h.ToString());
编辑:对于替换,您使用采用匹配评估器重载的替换方法
string result = r.Replace(line, new MatchEvaluator(replacementMethod));
public string replacementMethod(Match match)
{
return "?????";
}
解释正则表达式模式
首先,序列"(pattern1|pattern2|pattern3)"
意味着我们在字符串中找到三种可能的模式。其中一个足以匹配
第一种模式 -?0[Xx][A-Fa-f0-9]+
表示一个可选的减号,后跟一个零,后跟一个 X 或 x 字符,后跟一系列 A-F a-f 或 0-9 范围内的一个或多个字符
第二种模式-?'d+'.'d+
表示可选的减号,后跟一系列 1 位或多位数字,后跟小数点,后跟一系列 1 位或多位数字
第三种模式-?'d+
表示可选的减号,后跟一系列 1 位或多位数字。
模式的顺序至关重要。如果反转模式并将整数匹配放在十进制模式之前,则结果将是错误的。
除了正则表达式(它往往有自己的问题)之外,您还可以构建一个状态机来执行处理。您可以决定机器将接受哪些输入作为"数字"。与正则表达式不同,状态机将具有可预测的体面性能,并且还会为您提供可预测的结果(而正则表达式有时可以匹配相当令人惊讶的事情)。
当你想到它时,这并不难。状态相当少,您可以显式定义特殊情况。
编辑:以下是对评论的回应。
在.NET中,Regex被实现为NFA(Nontdeterminisitc Finite Automaton)。一方面,它是一个非常强大的解析器,但另一方面,它有时会回溯比它应该回溯的更多。当您接受不安全的输入(来自用户的输入,几乎可以是任何东西)时尤其如此。虽然我不确定您将使用哪种正则表达式来解析结果,但您可以在几乎任何事情中引起性能影响。尽管在大多数情况下,性能不是问题,但正则表达式性能可以随着输入呈指数级扩展。这意味着,在某些情况下,它确实可能是一个瓶颈。而且是一个相当出乎意料的。
正则表达式贪婪本质的另一个潜在问题是,有时它可以匹配意想不到的事情。您可能会使用相同的正则表达式数天,它可能会正常工作,等待解析被忽略字符的正确组合,最终会将垃圾写入数据库。
通过状态机,我的意思是使用确定性有限自动机或类似的东西解析输入。我会告诉你我的意思。下面是一个小的 DFA,用于解析字符串中的正十进制整数或浮点数。我很确定你可以使用像ANTLR这样的框架来构建DFA,尽管我敢肯定周围也有功能不那么强大的框架。