从字符串中删除随机表达式

时间:2012-12-31 10:03:47

标签: java sql regex oracle substr

我有一个像这样的字符串/列

String a = "000003023_AggregateStopLossLimit_W x3A 973911_2012-12-22.PDF";

我想创建一个子字符串,其中没有' x3A 973911'部分。

这意味着我想要这样的东西,

000003023_AggregateStopLossLimit_W_2012-12-22.PDF

有一个这样的字符串列表,它们具有不同的值,但格式相同。我希望删除字符串的一部分,它在第一个空格之后,在下一个'_'结束。

这就是我已经做过的,这很好用,但想知道是否有更好的方法。

String b = a.replaceAll(a.substring(a.indexOf(" "), a.indexOf("_",a.indexOf(" "))),"");

如果我可以在db本身(即oracle,而不是java)中执行此操作,那会更好。有没有想过直接使用select?

从列中获取这个格式化的字符串

还有一个要求,我不想显示文件的扩展名。在“。”之后没什么。应该显示,这意味着像'000003023_AggregateStopLossLimit_W_2012-12-22'这样的事情 我使用之前的APC解决方案尝试了以下内容

 select regexp_replace ( your_string
                          , '([^[:space]]*) (.*)_(.*)....'
                          , '\1_\3') as new_string from your_table

现在工作正常。
这应该删除最后4个字符,并且如果扩展名大于或小于3或者字符串没有被截断,则存在无法获得正确结果的风险。我正在寻找一种更美观的方式来做到这一点 有机会吗?

7 个答案:

答案 0 :(得分:4)

final String r = a.replaceAll(" .*?(?=_)", "");

如果你打印r,它会输出:

000003023_AggregateStopLossLimit_W_2012-12-22.PDF

答案 1 :(得分:3)

在数据库中执行此操作:

select regexp_replace ( your_string
                         , '([^[:space]]*) (.*)_(.*)'
                         , '\1_\3') as new_string
from your_table

不幸的是,Oracle在其正则表达式实现中没有任何强制执行惰性(非贪婪)的语法。这就是为什么我的原始'(。*)'包括x3A:它与最后一个空格匹配,后面跟着下划线。但是,否定语法会将字符串隔离到第一个空格。

  

“W失踪后的'_'。还有机会得到它吗?”

您可以随意格式化替换字符串。简单的方法是做我已经完成的工作,并在两个匹配的模式之间硬编码下划线。或者你可以把它作为一个搜索模式,并将它包含在替换字符串中(尽管你更喜欢用它来做更复杂的搜索)。


Oracle在10g中引入了正则表达式;功能涵盖in the documentation。正则表达式实现符合POSIX标准,因此它缺少Perl中可能遇到的一些功能。正则表达式支持在an appendix to the SQL ref.

中有详细说明

至于教程,我有一本很复杂的O'Reilly口袋书;我在Open World 2003获得了我的副本,但电子书的价格合理。 Buy it here。 Anotgher的良好起点是OTN论坛上cd的一系列主题:start reading here

答案 2 :(得分:2)

如果您需要SQL解决方案,这将更新行:

update yourtable
set field = substr(field, 0, instr(field, ' ')-1) || substr(field, instr(field, '_', instr(field, ' ')))
;

这将只显示转换后的值:

select
  yourtable.field,
  case
    when instr(field, '_', instr(field, ' '))>instr(field, ' ')
    then substr(field, 0, instr(field, ' ')-1) || substr(field, instr(field, '_', instr(field, ' ')))
    else field
  end as new_field
from
  yourtable

答案 3 :(得分:1)

replaceAll将正则表达式作为参数,如果子字符串包含正则表达式标记(例如[+),则会出现意外行为。

您可以使用replace来代替相同的东西但是将字符串作为参数。

除此之外,如果你知道你将有一个空格和_作为分隔符,并且其间的子字符串不会出现在其他地方,那么你的方法看起来很好。您可以使用中间变量使其更具可读性:

int start = a.indexOf(" ");
int end = a.indexOf("_", start);
String b = a.substring(0, start) + a.substring(end, a.length());

答案 4 :(得分:1)

除了您提供的代码中的正则表达式问题,我发现它也不太可读。

请尝试以下操作:

int f = a.indexOf(" ");
int l = a.lastIndexOf("_");
a = a.substring(0,f+1) + a.substring(l+1, a.length);

答案 5 :(得分:1)

答案 6 :(得分:0)

@Kent上面提供的Java解决方案非常优雅,我推荐它。也就是说,如果您想使用Oracle的正则表达式引擎来完成此任务,您可以尝试以下方法:

WITH t1 AS (
    SELECT '000003023_AggregateStopLossLimit_W x3A 973911_2012-12-22.PDF' AS filename
      FROM dual
)
SELECT filename, REGEXP_REPLACE(filename, ' [^_]*', '')
  FROM t1