【问题标题】:Match <keyword> with whitespace at end/start of line将 <keyword> 与行尾/行首的空格匹配
【发布时间】:2013-04-19 06:06:10
【问题描述】:

我不知道如何让 C# 正则表达式 IsMatch 匹配 &lt;keyword&gt; 后跟行尾或空格。

我目前有[\s]+keyword[\s]+,它适用于空间,但不适用于keyword&lt;end of string&gt;&lt;start of string&gt;keyword

我尝试过[\s^]+keyword[\s$]+,但这使它无法与空格匹配,并且在字符串的末尾或开头不起作用。

这是我尝试过的代码:

string pattern = string.Format("[\\s^]+{0}[\\s$]+",keyword);
if(Regex.IsMatch(Text, pattern, RegexOptions.IgnoreCase))

【问题讨论】:

  • 能否给个输入输出示例?
  • 如果正确是关键字输入的例子是'这是正确的' '这是正确的' '正确的' '也正确的' 错误的'fdcorrect' 'correctdfdfd'

标签: c# regex


【解决方案1】:

问题是字符类内部的^$ 不被视为锚点,而是被视为文字字符。您可以简单地使用交替而不是字符类:

string pattern = string.Format(@"(?:\s|^){0}(?:\s|$)",keyword);

请注意,不需要+,因为您只想确定是否有一个空格。你不在乎他们是否有更多。 ?: 只是一种很好的做法,它会抑制您在这里不需要的 capturing@ 使字符串成为逐字字符串,您不必在其中双重转义反斜杠。

还有另一种方式,我觉得它更简洁一些。您可以使用lookarounds,以确保您的关键字的左右两侧没有非空格字符(是的,双重否定,考虑一下)。如果存在空格字符或字符串有一端,则此假设有效:

string pattern = string.Format(@"(?<!\S){0}(?!\S)",keyword);

这完全一样,但可能效率更高一些(不过,您必须对其进行分析才能确定 - 如果它甚至重要的话)。

您还可以将第一个模式(具有非反转逻辑)与(正)环视一起使用:

string pattern = string.Format(@"(?<=\s|^){0}(?=\s|$)",keyword);

但是,这对第一个模式并没有真正的影响,除非您想在一个字符串中找到多个匹配项。

顺便说一句,如果您的keyword 可能包含正则表达式元字符(如|$+ 等),请务必先使用Regex.Escape 对其进行转义

【讨论】:

  • 如果前后有非空白字符,然后如果关键字不存在,您的前瞻/后视是否匹配。
  • @f1wade 我不确定你的意思。它只是满足您的规范 - 如果它立即被空格或字符串末尾包围,则它匹配 keyword。它也适用于较长的字符串,其中keyword 只是其中一个词。
  • 当您使用 \S 而不是 \s 时,我认为大写版本匹配非空格?
  • @f1wade 哦,我明白你现在的意思了。我有一个错字。第一个环视 sn-p 应该使用负环视。如果它们的内容匹配,它们会导致模式失败。这就是我所说的双重否定。
  • 感谢您与我一起运行,我的代码现在看起来像这样的字符串模式 = string.Format(@"(?
【解决方案2】:

我不完全确定你真的想用这个正则表达式完成什么,但是下面的代码将匹配字符串“关键字”,当它的两边都有空格时:

string resultString = null;
try {
    Regex regexObj = new Regex(@"\b(keyword)\b");
    resultString = regexObj.Match(subjectString).Value;
} catch (ArgumentException ex) {
    // Syntax error in the regular expression
}

一般可以解释为:\b 断言位置在词首和词尾的边界。在这种情况下,我假设感兴趣的词是关键字。

根据我对您问题的解释,我还认为您可能有兴趣匹配关键字后面的整个字符系列直到换行符。如果是这种情况,以下正则表达式代码将返回该匹配项:

string resultString = null;
try {
    Regex regexObj = new Regex(@"\bkeyword\b(\w*\s*)$");
    resultString = regexObj.Match(subjectString).Value;
} catch (ArgumentException ex) {
    // Syntax error in the regular expression
}

这个正则表达式可以解释为找到开始和结束的单词边界,这就是 \b 在两边的原因。 (\w*\s*)$ 读起来像这样匹配所有单词 \w 字符和空格字符 \s* 的出现次数,并将位置移动到 $ 行的末尾。

下一段代码将读入包含关键字的整行数据,不包含关键字的数据行将不匹配。

string resultString = null;
try {
    Regex regexObj = new Regex("^.*keyword.*$");
    resultString = regexObj.Match(subjectString).Value;
} catch (ArgumentException ex) {
    // Syntax error in the regular expression
}

解释:字符串开头的 ^ 位置,.* 匹配任何不是换行符的字符,然后包含关键字,后跟 .*,因此包含剩余的非换行符和$ 断言字符串末尾的位置,在本例中是整行。

我希望以上内容会有所帮助,如果不是这次,也许将来会有所帮助。我一直在尝试寻找替代实践来达到相同的结果,所以如果您有任何建设性的批评,请发表。

最好的祝愿, 史蒂夫

【讨论】:

    【解决方案3】:

    试试这个:

    string pattern = string.Format("^\\s*{0}\\s*$",keyword);
    

    【讨论】:

    • 我认为不允许在行首和关键字之间使用其他词。同样是行尾
    【解决方案4】:

    我发现了另一个帖子 How to specify "Space or end of string" and "space or start of string"?

    这回答了问题 所以我的代码现在是

    string pattern = string.Format("\\b+{0}\\b+",keyword);
    if(Regex.IsMatch(UserText, pattern, RegexOptions.IgnoreCase))
    

    【讨论】:

    • 你不应该认为+ 是完全没有必要的。 \b 不匹配字符,而是位置,因此它不会推进引擎的“光标”。因此\b\b\b\b 完全相同。此外,如果它像some string:keyword. 一样出现,这将匹配您的关键字,因为\b 匹配单词字符([a-zA-Z0-9_]... 在 .NET 中可能更多的 Unicode 字符)和非单词字符。如果您真的想将其限制为空格,请查看我的答案。
    • 所以 \b 匹配任何非 char 即 not[a-zA-Z0-9_]?
    • 我的意思是,it doesn't match any character at all, it matches a position.。例如,如果您的输入字符串是a-c(其中- 是一个非单词字符),那么模式\ba\b匹配a- 不是匹配的一部分,因为\b 只是检查两个相邻字符的位置,而实际上并未将它们包括在匹配中。这也意味着在这个例子中a\b-(这是一个有点毫无意义的模式)会给你一个匹配。
    猜你喜欢
    • 2021-10-15
    • 1970-01-01
    • 2011-12-18
    • 2017-05-21
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多