正则表达式提取部分字符串

时间:2014-07-29 08:12:10

标签: regex

我正在设置一些广告系列代码,这些代码将在网址中显示为查询参数。我想自动报告这些广告系列代码,并以这样的方式设置它们,即代码中的每个参数都有一组特定的值,这些值可以通过查找在系统中识别。但是,字符串的结尾部分是自由文本。这是一个例子:

socfb:obb:img:beg:rp:lo:mff:mffs201403_sbj1

如前所述,参数1-7可以是系统已知的许多不同值,我可以使用包含查询来提取每个值并在查找中使用它们以使其报告友好名。但是,如何提取字符串的最后一部分,例如mffs201403_sbj1,这是可选的,但始终是可变长度的自由文本,并且总是出现在第7个冒号之后。

另外,有没有办法只捕获mffs201403位,我总是使用下划线将两部分分开?这是因为第一部分标识了单个广告系列,而第二部分标识了该广告系列的变体(如果存在)。所以我想报告所有广告系列变体,例如: mffs201403_sbj1mffs201403_sbj2等,以及mffs201403整体。

我一直试图让我的头围在Regex的最长时间,我一直无法掌握它,所以如果有人能帮助我,我会非常感激

3 个答案:

答案 0 :(得分:2)

我不确定您使用的语言是什么,但这在c#中运行良好:

var input = "socfb:obb:img:beg:rp:lo:mff:mffs201403_sbj1";
var pattern = "^(?:[^:]+:){7}(?<last>(?<part1>[^_]+)_(?<part2>[^_]+))+$";
var match = Regex.Match(input, pattern);

if (match.Success)
{
    Console.WriteLine("Last: {0}", match.Groups["last"].Value);
    Console.WriteLine("Part1: {0}", match.Groups["part1"].Value);
    Console.WriteLine("Part2: {0}", match.Groups["part2"].Value);
}

输出:

Last: mffs201403_sbj1
Part1: mffs201403
Part2: sbj1

正则表达式的工作方式是找到“:以外的任何字符”后跟:,并重复7次。然后它会查找“_以外的任何字符”除以_,并将最后的部分放在不同的子组中,以便在代码中轻松提取它们。

如果你使用某种只采用正则表达式的第三方工具,我想这会更好用:

^(?:[^:]+:){7}([^_]*)_?([^_]*)$

子组1和2将包含最后一个变量的两个部分,但它也将处理没有最后一个变量的情况,或者它不包含_或任何部分之前的情况在_为空之后。

为了匹配最后一个变量,没有别的,可以使用这个正则表达式:

[^:]*$

$是字符串的结尾,我们在此之前匹配的所有内容都不是:

但是,要匹配字符串中间的某些内容,而不匹配周围的字符,它会有点棘手,甚至可能无法使用正则表达式。如果你知道字符串永远不会包含任何_,除了在最后一个变量中,你可以使用:

[^:]*_

其功能基本相同,但在匹配中始终包含_

答案 1 :(得分:0)

这样的事情对你有用:(\w+:){7}([^_]+)_(\w+)

这个正则表达式希望找到一个字符串,该字符串在重复7组字符后用下划线分隔(用\w表示,表示大写字母,小写字母数字和下划线)。

如果最后一个段不存在,则正则表达式将失败。可以找到一个工作示例here

在Java中,这将转化为:

public static void main(String[] args)
{
    Pattern p = Pattern.compile("(\\w+:){7}([^_]+)_(\\w+)");
    String str1 = "socfb:obb:img:beg:rp:lo:mff:mffs201403_sbj1";
    String str2 = "socfb:obb:img:beg:rp:lo:mff";

    Matcher m1 = p.matcher(str1);
    if(m1.find())
    {
        System.out.println(m1.group(2));
        System.out.println(m1.group(3));
    }
    else
    {
        System.out.println("No content found for " + str1);
    }

    Matcher m2 = p.matcher(str2);
    if(m2.find())
    {
        System.out.println(m2.group(2));
        System.out.println(m2.group(3));
    }
    else
    {
        System.out.println("No content found for " + str2);
    }
}

收率:

mffs201403
sbj1
No content found for socfb:obb:img:beg:rp:lo:mff

答案 2 :(得分:0)

对你的问题不是直接的答案,但是:如果这是在一个脚本中完成的,那么你真的不需要使用正则表达式。无论您使用哪种编程语言都应该使用字符串拆分功能,这种功能更易于使用且更具可读性。

例如在python中:

strings = query_parameter.split(":")
final_string = strings[-1]

然后拆分该字符串:

campaign = final_string.split("_")[0]
try:
    variant = final_string.split("_")[1]
except IndexError:
    variant = ""