【问题标题】:Java regexp substring extraction patternJava 正则表达式子字符串提取模式
【发布时间】:2012-09-28 10:05:49
【问题描述】:

我有这段文字:

<blockquote>1. тест1; тест2; </blockquote>
<blockquote>2. тест1; тест2; </blockquote>
<blockquote>1) тест1; тест2; </blockquote>
<blockquote>2) тест1; тест2; </blockquote>
<blockquote>1. 1) тест1; тест2; </blockquote>
<blockquote>1) 1. тест1; тест2; </blockquote>
<blockquote>1. тест </blockquote>

你能给我表达吗,用那个我可以提取тест1;回复2;在这些字符串中的任何一个变量?回复1;回复2; - 是西里尔字母。所以对于提取 тест 我需要使用 ([\p{IsCyrillic}]*) 表达式。

String pattern = "(.*)<blockquote>1. ([\\p{IsCyrillic}]*) </blockquote>(.*)";

仅适用于第一个变体。这种变体的表达方式是什么? (或者你可以给我每个字符串变体的特定表达吗?

【问题讨论】:

  • 我不认为这个正则表达式真的有效。 1; 2; \p{IsCyrillic} 不匹配。
  • with "(.*)
    1. ([\\p{IsCyrillic}]*)
    (.*)" 我只能提取 тест,不能提取 тест1; тест2;.
  • 你说得对。你能给我正确的表达方式吗?
  • 您需要首先定义您想要匹配的确切内容 - 除了西里尔字母之外还允许在匹配中使用什么?

标签: java regex pattern-matching expression


【解决方案1】:

对于您原始帖子中的所有字符串:-

String pattern = "(.*)<blockquote>[\\d[\\.\\)]\\s]+([[\\p{IsCyrillic}][\\d\\;\\s]+]+) </blockquote>(.*)";

对于下面给出的新要求字符串,请使用此模式。:-

String str = "<blockquote>1. тест </blockquote><blockquote>2. 1) ветка; метрика </blockquote>";

String p = "[(.*)<blockquote>[\\d[\\.\\)]\\s]+([[\\p{IsCyrillic}][\\d\\;\\s]+]+) </blockquote>(.*)]+";

好的,匹配并返回上述字符串中的所有三个тест, ветка; метрика,代码如下:-

String str = "<blockquote>1. тест </blockquote><blockquote>2. 1) ветка; метрика </blockquote>";

Pattern pattern1 = Pattern.compile("(тест)|(ветка;)|(метрика)");

Matcher matcher = pattern1.matcher(str);
while (matcher.find()) {
    System.out.print("Start index: " + matcher.start());
    System.out.print(" End index: " + matcher.end() + " ");
    System.out.println(matcher.group());
}

但是,由于您只是匹配 fixed 字符串,因此您实际上并不需要 regex。您可以只使用常规的String 类方法。使用String.substringString.indexOf 方法来查找您的字符串。 Regex 的真正威力在于在一个模式上匹配多个字符串。

【讨论】:

  • 中间看起来不对。它只匹配每个单词中的一个西里尔字母。
  • 我检查了这段文字:
    1。 тест
    2。 1) ? метрика
    它只返回ветка; метрика
  • 当然,为特定模式创建的正则表达式在其他模式下会失败。您需要准确指定要匹配的所有模式??
  • 好的,如果我有文本:
    1。 тест
    2。 1) ? метрика
    什么表达式返回тест?
  • 您希望它只返回 тест 吗?那为什么不直接比较呢??那你就不需要正则表达式了..
【解决方案2】:

这取决于您的具体要求。这是一个相当简单的修改,假设开头的编号可以是空格、右括号、点和数字的任意组合。

String pattern = 
 "(.*)<blockquote>[\\s\\.\\)\\d]+([\\p{IsCyrillic}\\;\\d\\s]*)</blockquote>(.*)";

更新:还进行了编辑,使中间部分匹配分号、数字和空格。

更新 2:在阅读了 cmets 中的讨论后,我不再确定需要什么,但这样做是匹配编号后的整个中间部分。匹配的部分可以是西里尔字符、分号、数字和空格的任意组合(只要它不以数字开头)。

【讨论】:

  • 这个表达式不适用于
    1。 слово
  • 您应该在第一个
    之后将 [\\s\\.\)\\d] 替换为 [\\d\\.\)\\s].. 作为它的 @ 987654322@
  • 它也有效。您可以添加此表达式片段以匹配
    1。 тест
  • @Jain,这应该没什么区别,因为在字符类中顺序并不重要。
  • @sperr0w,我不确定它是如何失败的。我认为这个问题可能没有明确定义。
【解决方案3】:

如果您只想检索тест1тест2。然后您可以使用String.substring()String.indexOf() 函数执行字符串搜索。在这种情况下不需要正则表达式。

但是如果标签可以包含不同的字符串,那么你可以使用下面的正则表达式。

(?&lt;= ).*?(?=(;| ))

这个正则表达式将分别选择块引用标签内的字符串。

<blockquote>1. тест1; тест2; </blockquote>
<blockquote>2. тест1; тест2; </blockquote>
<blockquote>1) тест1; тест2; </blockquote>
<blockquote>2) тест1; тест2; </blockquote>
<blockquote>1. 1) тест1; тест2; </blockquote>
<blockquote>1) 1. тест1; тест2; </blockquote>
<blockquote>1. тест </blockquote>

这将选择

тест1 тест2
тест1 тест2
тест1 тест2
тест1 тест2
1) тест1 тест2
1. тест1 тест2
тест

分别为所有标签。

如果您想从第 5 个和第 6 个标签中删除 1)1.,请相应地格式化您的字符串。

但是,如果您将所有标签都放在同一行中,那么它也会选择这些标签。您可以通过检查匹配的字符串是否以 &lt; 开头来过滤掉它们。

【讨论】:

    【解决方案4】:

    这里的模式看起来不错,应该可以工作。但是,有时我发现一步一步地做这样的事情更容易,例如:

      public static void main(String[] args){
    
        String[] testStrings = { "<blockquote>1. тест1; тест2; </blockquote>",
          "<blockquote>2. тест1; тест2; </blockquote>",
          "<blockquote>1) тест1; тест2; </blockquote>",
          "<blockquote>2) тест1; тест2; </blockquote>",
          "<blockquote>1. 1) тест1; тест2; </blockquote>",
          "<blockquote>1) 1. тест1; тест2; </blockquote>" };
    
        for (String testString : testStrings){
    
          String result = testString
            .replace("<blockquote>", "")
            .replace("</blockquote>", "")
            .replaceAll("\\d\\.|\\d\\)", "")
            .trim();
    
          System.out.println(result);
        }
      }
    

    【讨论】:

    • 我需要表达,而不是代码片段。真的,我有一个来自 StarDict Dictionary 文章的非常大的文本。
    • 这样效率低很多,也有潜在的问题。当然,它适用于示例数据,但其余数据是什么样的?您不再强制内部字符是西里尔字母,也不再检查事物是否以正确的顺序出现。如果&lt;blockquote&gt; 标记之外有东西,您将把它作为结果的一部分呈现。正则表达式是这项工作的正确工具。
    • 我明白了,但是我只想提一下,正则表达式并不总是一个好主意,有时编写和维护一个逐步完成的代码片段会更容易。此外,这看起来像他在解析 XML 或 HTML,也许应该在这里使用成熟的解析器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    相关资源
    最近更新 更多