【问题标题】:How to use regular expressions to match everything before a certain type of word如何使用正则表达式匹配特定类型单词之前的所有内容
【发布时间】:2009-02-17 23:48:38
【问题描述】:

我是正则表达式的新手。

是否可以匹配符合特定条件的单词之前的所有内容:

例如

这是一个测试 - - +++ 这是一个测试

我希望它遇到一个以大写开头且下一个字符为小写的单词。这构成了一个适当的词。然后我想删除那个词之前的所有内容。

上面的例子应该产生:This is a test

我只想进行此处理,直到找到正确的单词然后停止。

任何帮助将不胜感激。

谢谢

【问题讨论】:

  • 如果您没有到达我的“答案”的底部,请确保检查第二个插槽中的空格。为了提高可靠性,您可以检查“I”和“A”作为特例。此外,这会破坏您的示例“A TEST”将匹配。这不是一个很好的算法。

标签: java regex


【解决方案1】:

替换

^.*?(?=[A-Z][a-z])

使用空字符串。这适用于 ASCII 输入。对于非 ASCII 输入(Unicode、其他语言),应用不同的策略。

解释

.*?    Everything, until
(?=    followed by
[A-Z]  one of A .. Z and
[a-z]  one of a .. z
)

支持 Java Unicode 的变体是这样的:

^.*?(?=\p{Lu}\p{Ll})

【讨论】:

  • @Tomalak 谢谢,这真的很接近我想要的。它返回我不想要的值。有没有办法可以切换它返回我需要的字符串?
  • @Tomalak 从不介意这行得通。我非常感谢您的帮助以及其他提供帮助的人
【解决方案2】:

稍稍醒悟后,您无需删除任何内容,甚至无需创建子组 - 只需找到答案中其他地方表达的模式即可。这是一个完整的例子:

import java.util.regex.*;

public class Test
{
    public static void main(String args[])
    {
        Pattern pattern = Pattern.compile("[A-Z][a-z].*");

        String original = "THIS IS A TEST - - +++ This is a test";
        Matcher match = pattern.matcher(original);
        if (match.find())
        {
            System.out.println(match.group());
        }
        else
        {
            System.out.println("No match");
        }        
    }
}

编辑:原始答案

这看起来做对了:

import java.util.regex.*;

public class Test
{
    public static void main(String args[])
    {
        Pattern pattern = Pattern.compile("^.*?([A-Z][a-z].*)$");

        String original = "THIS IS A TEST - - +++ This is a test";
        String replaced = pattern.matcher(original).replaceAll("$1");

        System.out.println(replaced);
    }
}

基本上,诀窍不是忽略正确单词之前的所有内容 - 而是将从正确单词开始的所有内容分组,并用该组替换整个文本。

上面的操作会因"*** FOO *** I am fond of peanuts" 而失败,因为“我”不会被认为是一个正确的词。如果您想解决这个问题,请将 [a-z] 更改为 [a-z\s],这将允许使用空格而不是字母。

【讨论】:

  • 我认为从问题中他正在寻找正确单词之前的所有内容(而不是您的示例所示的其他方式)
  • 他想删除正确单词之前的所有内容。看看他的例子 - 他希望结果是“这是一个测试”,这正是我的代码产生的。
  • 然而,由于不同的误读,它比它需要的更复杂。正在编辑...
  • 你说得对,我误解了提问者的意思,然后我正在修复我的例子
  • 这是有效的,但有一种情况它不能 举个例子:这是一个测试 - - +++ 这是一个测试 第二个“这个”会导致问题。它删除了第一个“This”。在遇到第一个专有词后,我需要停止处理从而产生 This This is a test
【解决方案3】:

我知道我对此的看法确实不那么受欢迎,所以如果你们愿意的话,你们可以否决我让我被遗忘,但我不得不咆哮一下(这包含一个解决方案,只是不像海报那样要求)。

我真的不明白为什么人们这么快就使用正则表达式。

我已经完成了很多字符串解析(用于屏幕抓取 vt100 菜单屏幕),但我从来没有发现正则表达式比编写代码更容易的情况。 (也许一对夫妇会更容易一些,但不会太多)。

我有点理解,一旦你了解了它们,它们应该会更容易——但你看到有人提出这样的问题,并意识到每个程序员都不容易一眼就能理解。如果它花费了 1 个程序员 10 分钟的思考时间,那么即使你花了 5 分钟写 5 行代码,它也会比仅仅编写代码造成巨大的净损失。

所以它需要文档——如果同一级别的人遇到它,他将无法在没有他领域之外的知识的情况下修改它,即使有文档。

我的意思是,如果发帖人不得不问一个小事——那么根本就没有小事。

public String getRealText(String scanMe) {
    for(int i=0 ; i < scanMe.length ; i++)
        if( isUpper(scanMe[i]) && isLower(scanMe[i+1]) )
            return scanMe.subString(i);
return null; }

我的意思是它只有 5 行,但它比大多数(所有?)RE 解析器简单、易读且速度更快。一旦您将正则表达式包装在方法中并对其进行注释,大小的差异就无法测量。时间上的差异——对于发帖者来说显然要少很多时间——因为对于下一个遇到他的代码的人来说可能是这样。

这个字符串操作是 C 语言中使用指针更容易的操作之一——而且它会更快,因为测试函数是 C 语言中的宏。

顺便说一句,请确保在第二个插槽中查找空格,而不仅仅是小写变量,否则您会错过任何以单词 A 或 I 开头的行。

【讨论】:

    【解决方案4】:

    ([A-Z][a-z].+)

    会匹配:

    这是一段文字

    【讨论】:

      【解决方案5】:

      那么你可以做这样的事情

      '.*([A-Z][a-z].*)\s*'
      
      .* matches anything
      ( [A-Z] #followed by an uper case char 
        [a-z] #followed by a lower case 
        .*)   #followed by anything
        \s*   #followed by zeror or more white space
      

      我认为你在寻找什么

      【讨论】:

        猜你喜欢
        • 2018-12-21
        • 1970-01-01
        • 1970-01-01
        • 2019-11-12
        • 1970-01-01
        • 1970-01-01
        • 2018-07-18
        • 1970-01-01
        相关资源
        最近更新 更多