3

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

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 中执行此操作,那就更好了。任何想法直接使用选择从列中获取此格式化字符串?

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

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

这目前工作正常。
这应该删除最后 4 个字符,并且如果扩展名大于或小于 3 或字符串未被截断,则可能无法获得正确的结果。
我正在寻找一种更美观的方式来做到这一点。
任何机会?

4

7 回答 7

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

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

000003023_AggregateStopLossLimit_W_2012-12-22.PDF
于 2012-12-31T10:13:36.537 回答
3

要在数据库中执行此操作:

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

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

“W后面的'_'不见了。还有机会得到它吗?”

您可以随意格式化替换字符串。简单的方法是做我所做的,并硬编码两个匹配模式之间的下划线。或者,您可以将其作为自己的搜索模式并将其包含在替换字符串中(尽管对于更复杂的搜索,您更有可能这样做)。


Oracle 在 10g 中引入了正则表达式;文档中介绍了这些功能。正则表达式实现是 POSIX 兼容的,所以它缺少一些你在 Perl 中可能遇到的功能。正则表达式支持在 SQL ref 的附录中有详细说明。

至于教程,我有一本 O'Reilly 袖珍书,翻阅次数很多。我在 Open World 2003 上收到了我的副本,但是这本电子书价格合理。 在这里买。另一个好的起点是cdOTN 论坛上的一系列主题:从这里开始阅读

于 2012-12-31T11:02:11.843 回答
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
于 2012-12-31T11:01:32.773 回答
1

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

您可以replace改用它做同样的事情,但将字符串作为参数。

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

int start = a.indexOf(" ");
int end = a.indexOf("_", start);
String b = a.substring(0, start) + a.substring(end, a.length());
于 2012-12-31T10:06:47.907 回答
1

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

尝试以下操作:

int f = a.indexOf(" ");
int l = a.lastIndexOf("_");
a = a.substring(0,f+1) + a.substring(l+1, a.length);
于 2012-12-31T10:09:40.523 回答
1

您应该替换 REGEX_REPLACE 函数。

http://docs.oracle.com/cd/B12037_01/server.101/b10759/functions115.htm#SQLRF06302

于 2012-12-31T10:21:15.540 回答
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
于 2014-12-31T16:13:46.973 回答