如何在Oracle中删除文件扩展名(.docx,.pdf等),同时从单个列中分离出分隔数据

时间:2017-11-21 15:41:57

标签: sql oracle

所以给我这样的东西: (在这种情况下,3个空格是分隔符)

data_String (Column Name)
C:\Desktop(Filepath)   JSchmoe(username)   FileName.xml

我已设法将3个实体分成3个单独的列。然而;我有最后一步;我试图删除" .xml"来自FileName.xml。

我有以下但是它不起作用:

select 
   SUBSTR(SUBSTR(data_String, - instr(reverse(data_String), '   ' + 1)), 
   nullif( instr(SUBSTR(data_String, - instr(reverse(data_String), '   ') + 1), '.', -1) +1, 1) )

提前致谢!

3 个答案:

答案 0 :(得分:1)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE table_name ( data_string ) AS
SELECT 'C:\Desktop   JSchmoe   FileName.xml' FROM DUAL;

查询1 - 字符串函数

SELECT SUBSTR(
         data_string,
         1,
         INSTR( data_string, '   ' )
       ) AS filepath,
       SUBSTR(
         data_string,
         INSTR( data_string, '   ' ) + 3,
         INSTR( data_string, '   ', - 1 ) - INSTR( data_string, '   ' ) - 2
       ) AS name,
       SUBSTR(
         data_string,
         INSTR( data_string, '   ', -1 ) + 3,
         INSTR( data_string, '.', -1 ) - INSTR( data_string, '   ', -1 ) - 3
       ) As filename,
       SUBSTR(
         data_string,
         INSTR( data_string, '.', -1 ) + 1
       ) As extension
FROM   table_name

<强> Results

|    FILEPATH |     NAME | FILENAME | EXTENSION |
|-------------|----------|----------|-----------|
| C:\Desktop  | JSchmoe  | FileName |       xml |

查询2 - 正则表达式

SELECT REGEXP_SUBSTR( data_string, '^(.+?)   (.+?)   (.+)(\.(.*))?$', 1, 1, NULL, 1 )
         AS filepath,
       REGEXP_SUBSTR( data_string, '^(.+?)   (.+?)   (.+)(\.(.*))?$', 1, 1, NULL, 2 )
         AS name,
       REGEXP_SUBSTR( data_string, '^(.+?)   (.+?)   (.+)(\.(.*))?$', 1, 1, NULL, 3 )
         AS filename,
       REGEXP_SUBSTR( data_string, '^(.+?)   (.+?)   (.+)(\.(.*))?$', 1, 1, NULL, 5 )
         AS extension
FROM   table_name

<强> Results

|   FILEPATH |    NAME | FILENAME | EXTENSION |
|------------|---------|----------|-----------|
| C:\Desktop | JSchmoe | FileName |       xml |

答案 1 :(得分:1)

这是regexp派上用场的地方。这将删除句点字母后面的所有字母a-z,包括句点:

select regexp_replace(filename,'\.[a-zA-Z]+$') filename_wo_extension
from files;

如果您只想删除某些扩展程序,请使用:

regexp_replace(filename,'\.(docx|pdf|xml)$')

要包含数字-_,并将扩展中的字符最大数量限制为10:

regexp_replace(filename,'\.[a-zA-Z0-9\-\_]{1,10}$')

此限制不会更改filename.with.very_long_not_extension中的任何内容,但会删除最后的.long_ext

答案 2 :(得分:1)

假设某些文件可能没有扩展名,您也需要处理这种情况。如果你需要速度,它仍然可以用INSTR / SUBSTR完成;但是,使用正则表达式编写和维护更容易。类似的东西:

with
  inputs ( data_string ) as (
    select 'C:\Desktop   JSchmoe   FileName.xml'                from dual union all
    select 'E:\CD Drive   Someone Else   FileName_no_extension' from dual
  )
select regexp_substr(data_string, '(.*?)\s{3}', 1, 1, null, 1)              as filepath,
       regexp_substr(data_string, '(.*?)\s{3}', 1, 2, null, 1)              as username,
       regexp_substr(data_string, '(.*?\s{3}){2}(.*)(\.|$)', 1, 1, null, 2) as filename
from   inputs
;

FILEPATH     USERNAME         FILENAME               
------------ ---------------- ------------------------
C:\Desktop   JSchmoe          FileName                
E:\CD Drive  Someone Else     FileName_no_extension  

编辑:文件名可能包含多个点,例如'report.march2017.pdf'。在这种情况下,只有最后一个点及其后面的点必须被剥离。要处理这种情况,必须修改第三列的搜索模式。这是一种方式:

with
  inputs ( data_string ) as (
    select 'C:\Desktop   JSchmoe   FileName.xml'                from dual union all
    select 'E:\CD Drive   Someone Else   FileName_no_extension' from dual union all
    select 'F:\SomeDrive   mathguy   File.dot.ext'              from dual
  )
select regexp_substr(data_string, '(.*?)\s{3}', 1, 1, null, 1)              as filepath,
       regexp_substr(data_string, '(.*?)\s{3}', 1, 2, null, 1)              as username,
       regexp_substr(data_string, '(.*?\s{3}){2}(.*?)(\.[^.]*)?$', 1, 1, null, 2) as filename
from   inputs
;

FILEPATH     USERNAME         FILENAME               
------------ ---------------- ------------------------
C:\Desktop   JSchmoe          FileName                
E:\CD Drive  Someone Else     FileName_no_extension  
F:\SomeDrive mathguy          File.dot 
'(.*?\s{3}){2}(.*?)(\.[^.]*)?$'搜索模式的

说明

  • .*?匹配任意数量的字符(零个或多个),尽可能少 需要同时仍然允许匹配整个模式。
  • \s表示一个空格; \s{3}正好意味着三个空格。
  • (.*?\s{3}){2}表示两次出现(某些内容,尽可能短,后跟三个空格)。所以这应该把我们带到输入的第三个“部分”。
  • 现在从模式的末尾开始阅读:$是字符串结尾的锚点。
  • \.是一个单点字符。 [^.]是任何单个 -dot字符。 (\.[^.*]*)?表示:可选(如果可能) - 这就是问号的含义 - 一个点后跟零个或多个非点。那将是扩展,锚定在字符串的末尾。
  • 只剩下(.*):零个或多个字符,在第二次出现的三个空格和扩展名之间,如果有一个 - 如果不存在,则为字符串的结尾。这正是文件名,剥离了扩展名(如果有的话) - 并且它位于整个匹配模式的第二组括号中,因此我们可以在REGEXP_SUBSTR的最后一个参数中将其称为“2”。