正则表达式 - 忽略空格
Posted
技术标签:
【中文标题】正则表达式 - 忽略空格【英文标题】:Regex - Ignore the white spaces 【发布时间】:2021-09-13 23:49:12 【问题描述】:我有一个正则表达式:
Regex.Match(result, @"\bTop Rate\b.*?\s*\s*([\d,\.]+)", RegexOptions.IgnoreCase);
然后解析成int
topRate = int.Parse(topRateMatch.Groups[1].Value, System.Globalization.NumberStyles.AllowThousands);
示例)
Top Rate: 888,888
Output: 888888
通过使用我当前的正则表达式,我得到了 int 输出。 但是,我注意到当数字之间有空格时 例如,
Top Rate: 8 88,888
我只得到 8 分。有没有办法忽略数字之间/最高评分字母之后可能存在或不存在的任何空格?
示例)
Top Rate: 8 88,888
Expected output: 888888
Top Rate: 8 88,888
Expected output: 888888
Top Rate: 8 88,888
Expected output: 888888
Top Rate: 8 8 8,888
Expected output: 888888
Top Rate: 888, 8 88
Expected output: 888888
【问题讨论】:
中间块(带有->
)是什么意思?输入的规则是什么?给我们一些应该和不应该匹配的例子(以及为什么)
我会使用一种天真的解决方案,首先删除所有空格,然后再应用正则表达式来保持理智。
@Flydog57 这没什么意思。我只是想解释 888,888 ->(等于)888888
@MarkSouls 嗯嗯好的。如果可能的话,我试图添加 \s* 以使其工作。
@davis 如果你知道空格的位置就可以了,否则我怀疑它会变得相当复杂。
【参考方案1】:
首先,在匹配和捕获数字时不能跳过或省略空格,只能通过在给定字符串后提取多个匹配项来做到这一点。但是,有一个简单的两步方法。
您可以添加\s
来匹配任何空格,或者添加\pZs
和\t
来匹配任何水平空格到字符类。我建议先使用\d
捕获号码,然后使用可选的非捕获组,末尾带有数字模式,以确保捕获的号码以数字开头和结尾:
\bTop Rate\b.*?(\d(?:[\d,.\s]*\d)?)
请参阅regex demo。请注意,重复 \s*\s*
没有什么意义,\s*
已经匹配零个或多个空白字符,甚至 \s*
也是多余的,因为 .*?
尽可能少地匹配除 LF 字符之外的任何零个或多个字符。要使其跨行匹配,请添加 RegexOptions.Singleline
选项。
详情:
\bTop Rate\b
- 一个完整的词Top Rate
.*?
- 除换行符之外的任何零个或多个字符尽可能少
(\d(?:[\d,.\s]*\d)?)
- 第 1 组:
\d
- 一个数字
(?:[\d,.\s]*\d)?
- 一个可选的非捕获组,匹配零个或多个数字、,
、.
或空格,然后是一个数字。
接下来,当你得到匹配时,只保留数字。
var text = "Top Rate: 8 88,888";
var result = Regex.Match(text, @"\bTop Rate\b.*?(\d(?:[\d,.\s]*\d)?)", RegexOptions.Singleline);
if (result.Success)
Console.WriteLine( new string(result.Groups[1].Value.Where(c => char.IsDigit(c)).ToArray()) );
请参阅C# demo。多重匹配:
var text = "Top Rate: 8 88,888 and Top Rate: 8 \n 88,888";
var results = Regex.Matches(text, @"\bTop Rate\b.*?(\d(?:[\d,.\s]*\d)?)", RegexOptions.Singleline)
.Cast<Match>()
.Select(x => new string(x.Groups[1].Value.Where(c => char.IsDigit(c)).ToArray()));
foreach (var s in results)
Console.WriteLine( s );
见this C# demo。
【讨论】:
你总是杀死我所有的正则表达式问题!非常感谢你的帮助。这绝对有效。还有一件事。我最近将格式从 int 更改为 decimal。因此,当它到达 IsDigit 部分时,它只会产生 2,500.00 到 250000。我们可以让它像当数字有一个点 (2,500.50) 然后把它作为 2500.50 而当它没有 (888,888) 那么只有 888888.00 吗? @davis 试试this C# demo。我怀疑删除数字和点以外的任何字符都可以。 作品完美,,,永远欣赏它!【参考方案2】:这样的?
using System;
using System.Text.RegularExpressions;
public class Program
public static void Main()
string[] texts =
"This should Not match the Top Rate thing",
" Top Rate : 888,888 ",
"Top Rate : 8 8 8 , 8 8 8 ",
;
Regex rxNonDigit = new Regex(@"\D+"); // matches 1 or more characters other than decimal digits.
Regex rxTopRate = new Regex(@"
^ # match start of line, followed by
\s* # zero or more lead-in whitespace characters, followed by
Top # the literal 'Top', followed by
\s+ # 1 or more whitespace characters,followed by
Rate # the literal 'Rate', followed by
\s* # zero or more whitespace characters, followed by
: # a literal colon ':', followed by
\s* # zero or more whitespace characters followed by
(?<rate> # an named (explicit) capture group, containing
\d+ # - 1 or more decimal digits, followed by
( # - an unnamed group, containing
(\s|,)+ # - interstial whitespace or a comma, followed by
\d+ # - 1 or more decimal digits
)* # the whole of which is repeated zero or more times
) # followed by
\s* # zero or more lead-out whitespace characters, followed by
$ # end of line
", RegexOptions.IgnorePatternWhitespace|RegexOptions.ExplicitCapture );
foreach ( string text in texts )
Match m = rxTopRate.Match(text);
if (!m.Success)
Console.WriteLine("No Match: '0'", text);
else
string rawValue = m.Groups["rate"].Value;
string cleanedValue = rxNonDigit.Replace(rawValue, "");
Decimal value = Decimal.Parse(cleanedValue);
Console.WriteLine(@"Matched: '0' >>> '1' >>> '2' >>> 3",
text,
rawValue,
cleanedValue,
value
);
【讨论】:
【参考方案3】:我验证了,发现只要稍微改动一下Regex语句,就可以达到你的目的。
第一个:
第二个:
【讨论】:
我宁愿不使用 foreach 来完成这项任务,因为我需要多 30 行正则表达式来提取信息,所以这将是一场灾难,并且需要永远逐行提取。而且我已经只使用 if 语句来获取所有值就好了。以上是关于正则表达式 - 忽略空格的主要内容,如果未能解决你的问题,请参考以下文章
正则表达式 - 查找所有空格并忽略多行字符串中的连字符分隔的单词