2012-12-31 58 views
3

刪除隨機表達我有一個字符串/列這樣的事情從字符串

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

我想創建不具有部分' x3A 973911'在它的子字符串。

Whic意味着我想是這樣的,

000003023_AggregateStopLossLimit_W_2012-12-22.PDF 

有這樣的字符串,這將有不同的值,但該格式將是相同的列表。我想要刪除第一個空格後面的字符串部分,並在下一個'_'結束。

這就是我已經做的,這工作正常,但想知道是否有更好的方法來做到這一點。

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

如果我可以在數據庫本身,這是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或者字符串未被截斷,則可能會得不到正確的結果。
我正在尋找更美觀的方式來做到這一點。
有沒有機會?

+0

好的。我決定在查詢中這樣做。我現在需要的是在REGEXP_REPLACE sql函數中使用的正則表達式。請幫忙嗎? – jijo

+0

我的解決方案現在應該爲你工作 - 除非你有更多的皺紋;) – APC

+0

我需要一個更多的幫助,我不想顯示文件的擴展名。所以在''之後什麼都沒有。應該顯示,這意味着像這樣'000003023_AggregateStopLossLimit_W_2012-12-22'。任何機會? – jijo

回答

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袖珍手冊的大量副本;我在2003年開放世界獲得了我的副本,但電子書價格合理。 Buy it here。另一個好的起點是在OTN論壇上的cd的一系列線程:start reading here

+0

這沒有效果。 'x3A'即將出現在輸出中。 – jijo

+0

對不起,我錯過了文中多餘的空格。試試我修改後的代碼。 – APC

+0

它給了我這個000003023_AggregateStopLossLimit_W2012-12-22.PDF,但我想000003023_AggregateStopLossLimit_W_2012-12-22.PDF。 W之後的'_'缺失。還有什麼機會呢?感謝您的幫助 – jijo

1

replaceAll將正則表達式作爲參數,如果子字符串包含正則表達式標記(例如[,+例如),您將得到意外的行爲。

您可以使用replace而不是它做同樣的事情,但將字符串作爲參數。除此之外,如果你知道你將有一個空格和一個_作爲分隔符,並且其中的子字符串不會在其他地方出現,那麼你的方法看起來很不錯。你可以用中間變量使它稍微更易讀:

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

謝謝。無論如何,當我從數據庫本身檢索值時,在sql中執行它? – jijo

+0

@jijo Oracle plsql有一個[替換](http://www.techonthenet.com/oracle/functions/replace.php)函數,可能使您可以執行此操作。 – assylias

+0

但它有indexOf? – jijo

1

除了你提供的代碼中的正則表達式問題,我發現它的可讀性也較差。

嘗試以下操作:

int f = a.indexOf(" "); 
int l = a.lastIndexOf("_"); 
a = a.substring(0,f+1) + a.substring(l+1, a.length); 
4
final String r = a.replaceAll(" .*?(?=_)", ""); 
如果打印將R

,它給輸出:

000003023_AggregateStopLossLimit_W_2012-12-22.PDF 
+0

哇..好的。我希望這個網站有一個像Facebook一樣的'喜歡'按鈕:) – jijo

+0

@jijo它實際上有2個'喜歡'按鈕:你可以upvote你喜歡的答案,你可以接受你自己的問題的答案。 – assylias

+0

@jijo答案中的正則表達式由java支持。有前瞻'(?= _)'我在工作中也使用oracle作爲數據庫,但我並不是這方面的專家。你可以檢查oracle是否支持預讀,如果是的話,語法是什麼。如果你在java中進行替換,我的答案中的行應該給你想要的。 – Kent

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 
+0

我不想要更新表,因爲其他地方需要原始值。我需要的是一個選擇語句 – jijo

+0

@jijo請參閱更新回答 – fthiella

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