正则表达式提取单词的一部分

6

我有一个类似这样的文本:

my text has $1 per Lap to someone. 

请问如何从中提取出per部分?我知道如何提取出$的金额,方法如下:

new Regex(@"\$\d+(?:\.\d+)?").Match(s.Comment1).Groups[0].ToString()

任何帮助都将不胜感激。

请澄清一下:您想匹配 $、一个数字、per 和一个单词;并捕获数字和单词吗? - Richard
@Kasra 这只是一个字符串类型。 - Sampath
@Richard 不需要,我只需要挑选或检查上述文本中是否有“per”部分。 - Sampath
@Sayse 只是检查字符串是否包含“per”。 - Sampath
1
那么就使用这种方法,你不需要正则表达式。 - Sayse
显示剩余7条评论
4个回答

2

如果您需要从一个较大的字符串中获取多个子字符串,可以使用捕获组。

要获取per部分,请使用以下正则表达式并获取Groups[2].Value

var str = "my text has $1 per Lap to someone. ";
var per_str = new Regex(@"(\$\d+(?:\.\d+)?)\s*(\p{L}+)").Match(str).Groups[2].Value;

输出:

在此输入图片描述

用于捕获per的正则表达式是\p{L}+,其中\p{L}捕获所有Unicode字母(例如фё),而不仅仅是拉丁字母。

要获取数字部分,请使用相同的正则表达式,但抓取Groups[1].Value:

var num_str = new Regex(@"(\$\d+(?:\.\d+)?)\s*(\p{L}+)").Match(str).Groups[1].Value;

输出:

在此输入图片描述

另一个提示:如果您计划在应用程序执行期间多次使用它,请首先编译您的正则表达式

var rx = new Regex(@"(\$\d+(?:\.\d+)?)\s*(\p{L}+)", RegexOptions.Compiled);
var per_str = rx.Match(str).Groups[2].Value;
var num_str = rx.Match(str).Groups[1].Value;

如果您只需要在$后面的数字,只需在正则表达式中在其后放置开放的圆括号:@"\$(\d+(?:\.\d+)?)\s*(\p{L}+)"
同时,您可以使用以下方法一次获取所有组:
var groups = rx.Matches(str).Cast<Match>().Select(p => new { num = p.Groups[1].Value, per = p.Groups[2].Value }).ToList();

enter image description here

编辑:

如果你只想匹配数字后面的per,你可以使用@"(\$\d+(?:\.\d+)?)\s*(per)"或(不区分大小写)@"(\$\d+(?:\.\d+)?)\s*((?i:per\b))"


但它不仅选择 per,还选择其他的。就像这样。假设我有这样的文本 my text has $1 to Lap to someone.。然后它会选择 to。我该如何避免选择其他的?提前致谢。 - Sampath
1
使用文字 per: @"(\$\d+(?:\.\d+)?)\s*(per)\b"。然而,我认为没有必要加一个捕获组,因为你已经知道它是 "per"。除非可以是小写或大写的形式。那么,请使用 @"(\$\d+(?:\.\d+)?)\s*((?i:per)\b)" - Wiktor Stribiżew
非常感谢您的支持 :) - Sampath

1

正如你所说,per 是一个字符串类型,下面这个简单的正则表达式可以为你完成这项工作:

\$\d+\s([a-zA-Z]+)

但是如果 per 包含数字,您可以使用匹配单词字符的 \w

\$\d+\s(\w+)

演示

注意,在这种情况下 per 位于第一个捕获组中,您需要提取第一组。

如果您不想使用分组,也可以使用正向查找:

(?<=\$\d+\s)[a-zA-Z]+

如果“per”是一个特殊单词,您可以使用以下正则表达式进行检查:
(?<=\$\d+\s)per

类似于:

var per_str = new Regex(@'(?<=\$\d+\s)per').Match(str).Groups[0].Value;
if (per_str != ''){
#dostuff
}

我已经使用了另一种方式,但它不仅选择 per,还选择了其他的。就像这样。假设我有这样一个文本:我的文字中有 $1 到 Lap 给某人。,然后它就选择了 to。我如何避免选择其他的?谢谢。 - Sampath
@Sampath,你的意思是per是一个特殊的单词吗? - Mazdak
我已经使用了 (?<=\$\d+\s)per,在没有组的情况下它仍然有效。但是在你的例子中,你使用了组。有什么想法吗? - Sampath
@Sampath 我觉得你对正则表达式还不够熟悉!你可以从这里开始学习 http://www.regular-expressions.info/quickstart.html - Mazdak
这里有一些误解,非常抱歉。你给了我一个非常好的答案,非常感谢。但是我只想知道是否可以在没有组的情况下使用它?这是唯一的问题。因为我已经在没有组的情况下使用它,并且它可以工作。在最后一个例子中,你使用了Groups和(?<=\$\d+\s)per。这是必要的吗?谢谢。 - Sampath
显示剩余7条评论

0

正如@Sayse所说,您在此处不需要使用正则表达式。我提供了两个没有使用正则表达式的解决方案。

请查看演示或阅读代码:

public static void Main()
{
    var s = "my text has $1 per Lap to someone.";

    Console.WriteLine(Test(s));
    Console.WriteLine(Test2(s));
}

static object Test(string s)
{           
    var tab = s.Remove(s.IndexOf(" Lap"))       // remove everything after " Lap" 
               .Substring(s.IndexOf(" $") + 2)  // remove everything before " $"
               .Split(' ');

    return new { Amount = tab[0], Per = tab[1] };
}

static object Test2(string s)
{
    var tab = s.Split(' ');
    var amount = tab.Single(t => t.StartsWith("$")).Substring(1);
    var per = tab[Array.FindIndex(tab, t => t.StartsWith("$")) + 1];

    return new { Amount = amount, Per = per };
}

输出

{ Amount = 1, Per = per }
{ Amount = 1, Per = per }

1
是的,就像我说的,我们有亿万行代码,而不是三行。 - Wiktor Stribiżew
Test() 函数中,只有两行代码,如果你直接返回数组 tab,那么可以将其合并为一行。 - aloisdg

0
(?<=\$\d+(?:\.\d+)?\s+)\S+

这应该对你有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接