java正则表达式-应用程序名称替换

java正则表达式-应用程序名称替换,java,regex,Java,Regex,我需要帮助从其作业名称中获取相关应用程序名称 Job Name | App Name --------------------------------------------- ---------- JOB:Level1_OSP_DEF_1_1443534637_3mqku88i_1_0 OSP_DEF_1 JOB:Level0_GRSPOL_1423634637_20afoikl_1_1 GRSPOL JO

我需要帮助从其作业名称中获取相关应用程序名称

Job Name                                     | App Name
---------------------------------------------  ----------
JOB:Level1_OSP_DEF_1_1443534637_3mqku88i_1_0   OSP_DEF_1
JOB:Level0_GRSPOL_1423634637_20afoikl_1_1      GRSPOL
JOB:Level1_DSP_113_%I_3qqkv2vk_1_1             DSP_113
JOB:Level0_BPKMG_12_1238534637_2a4foik1_1_0    BPKMG_12
我尝试了一些正则表达式,但它并不能一直产生正确的结果

JOB:*.*?_(.*?)_[*\d|%I]+_.*
JOB:*.*?_(.*?)_[t]*\d+?_.*
规则:-

1. The App name can have a max. of 9 characters including "_" in middle.
2. The App name is present after the 1st "_" and always ends with "_".
3. The Alphabets in App Name will always be in CAPS.

此类regexp适用于所有示例:

"JOB:Level\\d+_([A-Z0-9_]{1,9})_(\\d+|%I)_\\w+_\\d+_\\d+"
下面是演示它的代码:

public class RegexTest {
    public static String extractJob(String input) {
        Pattern pattern = Pattern.compile("JOB:Level\\d+_([A-Z0-9_]{1,9})_(\\d+|%I)_\\w+_\\d+_\\d+");
        Matcher m = pattern.matcher(input);
        if (m.matches()) {
            return m.group(1);
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println(extractJob("JOB:Level1_OSP_DEF_1_1443534637_3mqku88i_1_0"));
        System.out.println(extractJob("JOB:Level0_GRSPOL_1423634637_20afoikl_1_1"));
        System.out.println(extractJob("JOB:Level1_DSP_113_%I_3qqkv2vk_1_1"));
        System.out.println(extractJob("JOB:Level0_BPKMG_12_1238534637_2a4foik1_1_0"));
    }
}

假设应用程序名称应该是符合3个已定义规则的最长子字符串(未声明规则),并且作为名称,它仅限于大写字母(规则#3)、数字(未声明规则)和下划线(规则#1):

请注意,此正则表达式不限制第一个
\uu
前面的文本,也不限制终止应用程序名称的
\u
后面的文本。这完全符合规则,没有任何此类限制

试验

输出

OSP_DEF_1
格斯波尔
DSP_113
BPKMG_12

基于这些示例,我假设作业由六个字段连接,这些字段之间用下划线分隔。查找应用程序名称的想法是删除第一个字段和后面的四个字段。如果应用程序名称的规则发生更改(允许使用不同的字符或长度),这将使提取规则更简单、更健壮

一个例子来解释

JOB:Level1_OSP_DEF_1_1443534637_3mqku88i_1_0
    +----+ +-------+ +--------+ +------+ + +
       |       |          |         |    | |
       |       |          |         |    | +- field 6
       |       |          |         |    +--- field 5
       |       |          |         +-------- field 4
       |       |          +------------------ field 3
       |       +----------------------------- field 2
       +------------------------------------- field 1
代码保留所有内容,直到第一个
,包括(
作业:Level1
在正则表达式中由
[^.]*.
匹配)和以
.
开头的尾部(字段2和3之间的分隔符),并包含其他三个
.
(字段4、5、6之间的分隔符)。尾部在正则表达式中由
({4}
匹配。在正则表达式中,
(.*)
与字段1和字段4匹配

String[] jobs = { "JOB:Level1_OSP_DEF_1_1443534637_3mqku88i_1_0", 
    "JOB:Level0_GRSPOL_1423634637_20afoikl_1_1",
    "JOB:Level1_DSP_113_%I_3qqkv2vk_1_1",
    "JOB:Level0_BPKMG_12_1238534637_2a4foik1_1_0"};
for (String job : jobs) {
    System.out.printf("%-45s - %s%n", job, job.replaceAll("[^_]*_(.*)(_.*){4}", "$1"));
}
输出

JOB:Level1_OSP_DEF_1_1443534637_3mqku88i_1_0  - OSP_DEF_1
JOB:Level0_GRSPOL_1423634637_20afoikl_1_1     - GRSPOL
JOB:Level1_DSP_113_%I_3qqkv2vk_1_1            - DSP_113
JOB:Level0_BPKMG_12_1238534637_2a4foik1_1_0   - BPKMG_12

您希望通过
[*\d|%I]
[t]
实现什么?您的规则没有充分描述应用程序名称。在第一个示例行中,您试图匹配OSP_DEF_1,但是“OSP”、“OSP_DEF”、“OSP_DEF_1”都满足3个条件。@Greg,只想更新需要符合的规则。@ajb,早期的正则表达式曾经工作过,但由于环境发生了一些变化,正则表达式由于名称的变化而失败。嗯,您尝试过的正则表达式中的那些模式看起来像只在一些非常特定的示例中有效的东西。因此,当更多的例子出现时,它们就会停止工作,这也就不足为奇了。你的正则表达式如何遵守应用程序名称最多可以包含9个字符的规则?在任何情况下,一个适用于4个示例的正则表达式都不是一个充分的答案,因为这并不能证明它适用于所有其他示例。而且,与许多海报要求我们写一个正则表达式,将字符串Y从字符串X中提取出来不同,这张海报实际上给了我们他希望正则表达式遵循的规则,尽管这些规则模糊不清,我们需要与他进一步合作。@ajb,9个符号限制添加。OPs规则远不能完全描述他的问题,因此不可能“证明它对所有其他示例都有效”,因为规则没有严格定义所有可能示例的集合。@TagirValeev,非常感谢您的正则表达式。。。我对它做了一点修改并发布了{JOB.*\\d(a-Z0-9.]{1,9}){u(\\d+\124;%I).*}。。。如果可能的话,你能检查一下是否有较短的方法吗?@Marcos修改后的正则表达式中的第一个
*
可以匹配
,违反规则2。还要注意的是,除了“第一个”定义中隐含的“不是一个
”之外,没有任何规则规定对第一个
\uu
之前的内容有任何限制。您的正则表达式和这个答案都有额外的限制。@Marcos,一般来说,正则表达式应该是有效的,而不是简短的。在中间使用<代码> .*/COD>可能会由于广泛的回溯而降低性能。如果在您的情况下,性能不是一个大问题,那么它可能是正常的。字符串不一定总是有6“389;”,也可以有5或7。@Marcos示例中介绍了这一点<对于
GRSPOL
而言,代码>5
;对于
OSP_DEF_1
而言,代码>7。我假设字段的数量始终为六个,并且它们由
\uuu
连接。因此,如果删除第一个和最后四个字段,剩下的就是第二个字段。独立于第二个字段中有多少个
。我更新了我的答案,使之更加清晰。感谢你的回答…这似乎是性能、灵活性和正则表达式长度方面的最佳答案…我会想到这样的事情。不过,要记住一点:如果你有一个不兼容的应用程序。名称(特别是太长),匹配程序将找不到任何内容(例如
Level1\u iamatolongapplicationname\u something
)。如果需要,在这种情况下,可以调整正则表达式以返回类似于
IAMATOOLO
的内容。如果这不是你可能遇到的情况,这将是一个无用的复杂问题,然而,这个答案已经是完美的。
String[] jobs = { "JOB:Level1_OSP_DEF_1_1443534637_3mqku88i_1_0", 
    "JOB:Level0_GRSPOL_1423634637_20afoikl_1_1",
    "JOB:Level1_DSP_113_%I_3qqkv2vk_1_1",
    "JOB:Level0_BPKMG_12_1238534637_2a4foik1_1_0"};
for (String job : jobs) {
    System.out.printf("%-45s - %s%n", job, job.replaceAll("[^_]*_(.*)(_.*){4}", "$1"));
}
JOB:Level1_OSP_DEF_1_1443534637_3mqku88i_1_0  - OSP_DEF_1
JOB:Level0_GRSPOL_1423634637_20afoikl_1_1     - GRSPOL
JOB:Level1_DSP_113_%I_3qqkv2vk_1_1            - DSP_113
JOB:Level0_BPKMG_12_1238534637_2a4foik1_1_0   - BPKMG_12