构建正则表达式模式以最终从数据中选择所需的文本

Posted

技术标签:

【中文标题】构建正则表达式模式以最终从数据中选择所需的文本【英文标题】:Building Regex pattern to eventually pick the desired text from the data 【发布时间】:2020-08-24 02:39:08 【问题描述】:

我正在从应用程序 UI 中的 TextArea 获取一些文本数据。 最终目标是从这个 TextArea 的整个数据中识别出预先确定的文本格式/模式。 (如果有的话,我将进一步使用此类过滤掉的文本来进一步处理此类文本中的员工 ID)

有效的模式是:

    EMP 以及此处的任何有效 ID。例如电磁脉冲 1234 具有此固定模式的 URL:http://emps/id 例如http://emps/1234

我将从源数据中搜索此类模式文本。

这是我迄今为止开发的一堆正则表达式模式和相关逻辑:

string sourceText = "This will contain a bunch of text. Might also contain EMP 1234 and there could be a bunch of text after this pattern. There could again be EMP 4567 or http://emps/2345 We'll be extracting all such patterns. 3 in this case." 
const string regexPattern =
    "(\\bEMP(s|(id)|:|#)?\\s*?(id|#)?\\s*?(:|#)?\\s1)(?<EMPid>(\\d1,11))(\\s*?(,|(and))\\s*?(?<EMPidnew>(\\d1,11)))*";

var search = new Regex(regexPattern , RegexOptions.IgnoreCase);

MatchCollection matches = searcher.Matches(sourceText );

foreach (Match match in matches)

    //If we reach this point it means that the sourceText contained text which matched our pattern
    // From this point I'll be extracting the ID and process it further

REGEX 不区分大小写,这是有意的。 到目前为止,我开发的 REGEX 通过从一些网站获取语法参考,正确处理了我的第一个模式,即:

EMP 以及此处的任何有效 ID。例如EMP 1234

但现在我不确定如何修改现有的正则表达式模式或添加到现有的模式以进一步满足我的第二个要求,即 具有此固定模式的 URL:

http://emps/id 例如http://emps/1234

【问题讨论】:

您可以使用肯定的前瞻断言模式的出现,或者如果 url 应该始终在它之前或之后,您可以匹配它。 您使用* 零个或多个 的模式将在处理文本时导致显着回溯;为了避免不要使用*,而是使用+一个或多个。如果您使用* 来显示不同内部模式之间的模糊性,请尝试使用| 而不是两个单独的* ID 总是从头开始跟踪吗?号码后面可以有文字吗?您能否提供更多示例来显示预期的条件。 ? @ΩmegaMan,ID 只能是数字。在预期的模式之后可能会有额外的文本。我更新了代码示例中的 sourceText 变量值。 也许使用 2 个命名的捕获组 \b(?:EMP(?:id|[s:#])?\s+(?&lt;EMPid&gt;\d1,11)|(?&lt;EMPurl&gt;https?://emps/\d+))(?!\S) regex101.com/r/CtBiWX/1 【参考方案1】:

您可以稍微缩短您的模式,并使用与其中一种模式匹配的替代方案。

说明

\b字边界 (?: 交替的非捕获组 EMP 字面匹配 (?:id|[s:#])? 可选择匹配 id 或 s :# 之一 \s+ 匹配 1+ 个空格字符 (?&lt;EMPid&gt;\d1,11)命名组EMPid,匹配1-11位数字 |或者 (?&lt;EMPurl&gt;https?://emps/\d+) 命名组 EMPurl 匹配 url 模式 )关闭非捕获组 (?!\S) 负前瞻,断言右侧不是非空白字符(右侧空白边界)

Regex demo | C# demo

示例代码

string sourceText = "This will contain a bunch of text. Might also contain EMP 1234 and there could be a bunch of text after this pattern. There could again be EMP 4567 or http://emps/2345 We'll be extracting all such patterns. 3 in this case.";
const string regexPattern = @"\b(?:EMP(?:id|[s:#])?\s+(?<EMPid>\d1,11)|(?<EMPurl>https?://emps/\d+))(?!\S)";
var search = new Regex(regexPattern , RegexOptions.IgnoreCase);
MatchCollection matches = search.Matches(sourceText);

foreach (Match match in matches)

    Console.WriteLine(match.Value.ToString());

输出

EMP 1234
EMP 4567
http://emps/2345

【讨论】:

谢谢@第四只鸟。我已经根据我的需要稍微调整和利用了您的正则表达式的 URL 部分并进一步使用它: (http(s)?://emps/(\\d1,11)) 'emps 后面的括号/' 将帮助我在 MatchCollection 中将 ID 作为隔离值获取。【参考方案2】:

有效的模式是:

    EMP 以及此处的任何有效 ID。例如EMP 1234 具有此固定模式的 URL:http://emps/id 例如http://emps/1234

查看代码中的正则表达式表明您想要方式超越您在报价中所说的内容。对于正则表达式,我只会使用:

(https?://emps/|\bEMP\b\s*)(?<EMPid>\d1,11)

【讨论】:

【参考方案3】:

据我所见,连续位(两个或更多)的简单匹配将完成\d2,的工作。

使用您的示例,以下是在 3 个单独的匹配项中捕获的内容(in gold):

当然,您可以通过知道员工编号至少有 4 位来改进逻辑,因此请使用 \d4,

它们是否以特定数字开头,比如 9?然后加上 9\d3,


需要Emp的前缀还是网址?然后从(EMP\s|/) 的这种模式构建,我们在其中查找 emp 或 URL 的正斜杠。如((EMP\s|/)\d2,)


这里的重点是,您可以根据基本原则来找到匹配项。如果需要整个 URL,则添加到上面提供的构建块中。

【讨论】:

以上是关于构建正则表达式模式以最终从数据中选择所需的文本的主要内容,如果未能解决你的问题,请参考以下文章

构建正则表达式模式以适应所有这些单词

是否可以比较一行中的两个值并获取所需的值,但这两个值都与写入的正则表达式匹配

Python:正则表达式与所需的相反[重复]

正则表达式的基础问题

简析正则表达式

文本文件规范化和模式匹配