I'm looking to use REGEXP_REPLACE (or equivalent functions) to format my strings to be fixed length outputs.
For example. My input is always 3 sets of random strings, delimited by commas.
I want the output to have a fixed length of 10 characters (filled by '_') for each capturing group.
input:
abc,def,ghi
085,10,1234567
long words,tom,jerry
Desired output:
_______abc_______def_______ghi
_______085________10___1234567
long words_______tom_____jerry
So the code would be something like:
select regexp_replace( input, '([^,]+),([^,]+),([^,]+)',
LPAD('\1', '_', 10) || LPAD('\2', '_', 10) || LPAD('\3', '_', 10) )
from <table>
That apparently didn't work out as expected.
Any ideas?
With multiple replacements and concatenation you can do this:
select
lpad(regexp_replace('085,10,1234567', ',.*$', ''), 10, '_') || -- remove the first period and everything after it
lpad(regexp_replace('085,10,1234567', '^[^,]+,|,[^,]+$', ''), 10, '_') || -- remove the first period, everything before it, and the last period plus everything after it
lpad(regexp_replace('085,10,1234567', '^.*,', ''), 10, '_') as whatever -- remove the last period and everything before it
from
dual
Just replace '085,10,1234567' with your input.
This example produces:
_______085________10___1234567
Related
Is there a way to simplify this query using only one regexp_replace?
select regexp_replace(regexp_replace('BL 081', '([^0-9.])', '', 'g'), '(^0+)', '', 'g')
the result should be 81
I'm trying to remove all non-numeric chars and leading 0's from the result
You can do this by capturing the digits you want (not including any leading zeros) and removing everything else:
select regexp_replace('BL 0081', '.*?([1-9][0-9]*)$', '\1')
Output
81
Note you don't need the g flag as you are only making one replacement.
Demo on dbfiddle
Why not just change the range from 0-9 to 1-9?
regexp_replace('BL 081', '(^[^1-9]+)', '', 'g')
This pattern should do: \D+|(?<=\s)0+
\D - matches characters that are not digits
(?<=\s) - looks behind for spaces and matches leading zeros
You can use 1 fewer regexp_replace:
select regexp_replace('BL 081', '\D+|(?<=\s)0+', '', 'g')
# outputs 81
alternatively, if you are interested in the numeric value, you could use a simpler regex and then cast to an integer.
select regexp_replace('BL 081', '\D+', '')::int
# also outputs 81, but its type is int
I need 3 characters minimum for users accounts. I reuse existing names like
"tata-fzef - vcefv" or "kk" from the IMP_FR field to make this accounts.
In the second exemple, "kk" should become "k_k" because less than 3 characters.
How to do it with Postgresql?
regexp_replace( IMP_FR , regexp, first_character + '_' + last character, 'g')
Regular expressions won't help much here since REGEXP_REPLACE does not support conditional replacement patterns. You need different replacement pattern here for cases when the input only contains one, two or three or more chars.
So, it is better to rely on CASE ... WHEN ... ELSE here and the regular string manipulation functions:
CREATE TABLE tabl1
(s character varying)
;
INSERT INTO tabl1
(s)
VALUES
('tata-fzef - vcefv'),
('kkk'),
('kk'),
('k')
;
SELECT
CASE
WHEN LENGTH(s) = 1 THEN '_' || s || '_'
WHEN LENGTH(s) = 2 THEN LEFT(s,1) || '_' || RIGHT(s,1)
ELSE s
END AS Result
FROM tabl1;
See the online demo. Result:
I have attempted to use this question here Splitting string into multiple rows in Oracle and adjust it to my needs however I'm not very confident with regex and have not been able to solve it via searching.
Currently that questions answers it with a lot of regex_substr and so on, using [^,]+ as the pattern so it splits by a single comma. I need it to split by a multi-character delimiter (e.g. #;) but that regex pattern matches any single character to split it out so where there are #s or ;s elsewhere in the text this causes a split.
I've worked out the pattern (#;+) will match every group of #; but I cannot workout how to invert this as done above to split the row into multiple.
I'm sure I'm just missing something simple so any help would be greatly appreciated!
I think you should use:
[^#;+]+
instead of
(#;+)
As, it will be checking for any one of the characters in the range which can be # ; or + and then you can split accordingly.
You can change it according to your requirement but in the regex I
shared, I am consudering # , ; and + as delimeter
So, in end, the query would look something like this:
with tbl(str) as (
select ' My, Delimiter# Hello My; Delimiter World My Delimiter My Delimiter test My Delimiter ' from dual
)
SELECT LEVEL AS element,
REGEXP_SUBSTR( str ,'([^#;+]+)', 1, LEVEL, NULL, 1 ) AS element_value
FROM tbl
CONNECT BY LEVEL <= regexp_count(str, '[#;+]')+1\\
Output:
ELEMENT ELEMENT_VALUE
1 My, Delimiter
2 Hello My
3 Delimiter World My Delimiter My Delimiter test My Deli
-- EDIT --
In case you want to check unlimited numbers of # or ; to split and don't want to split at one existence, I found the below regex, but again that is not supported by Oracle.
(?:(?:(?![;#]+).#(?![;#]+).|(?![;#]+).;(?![;#]+).|(?![;#]+).)*)+
So, I found no easy apart from below query which will not split on single existence if there is only one such instance between two delimeters:
select ' My, Delimiter;# Hello My Delimiter ;;# World My Delimiter ; My Delimiter test#; My Delimiter ' from dual
)
SELECT LEVEL AS element,
REGEXP_SUBSTR( str ,'([^#;]+#?[^#;]+;?[^#;]+)', 1, LEVEL, NULL, 1 ) AS element_value
FROM tbl
CONNECT BY LEVEL <= regexp_count(str, '[#;]{2,}')+1\\
Output:
ELEMENT ELEMENT_VALUE
1 My, Delimiter
2 Hello My Delimiter
3 World My Delimiter ; My Delimiter test
4 My Delimiter
I have one oracle table with one of the columns having below values,
,21A,22,21,28,28
I want to do a regex replace for removal of ,21 (The exact match) but it removes the value from ,21A
Below is my query,
update STUDENT set SCORES = REGEXP_REPLACE(SCORE, ',21' , '', 1, 1) where STUDENT_ID = 1;
How can this be achieved? Any ideas?
In your case, you can use a ,21(\W|$) regex. It matches ,21 that is followed with a non-word character or the end of string.
REGEXP_REPLACE(SCORE, ',21(\W|$)' , '\1', 1, 1)
Here is how you can perform a whole word search and replace in Oracle SQL:
regexp_replace(
haystack
, '(\W|^)(' || what_to_replace || ')(\W|$)'
, '\1' || with_what || '\3'
, 1
, 0
, 'imn'
)
I already found out I need to use substr/instr or regex but with reading the documentation about those, I cant get it done...
I am here on Oracle 11.2.
So here is what I have.
A list of Strings like:
743H5-34L-56
123HD34-7L
12HSS-34R
23Z67-4R-C23
What I need is the number (length 1 or 2) after the first '-' until there comes a 'L' or 'R'.
Has anybody some advice?
regexp_replace(string, '^.*?-(\d+)[LR].*$', '\1')
fiddle
Another version (without fancy lookarounds :-) :
with v_data as (
select '743H5-34L-56' val from dual
union all
select '123HD34-7L' val from dual
union all
select '12HSS-34R' val from dual
union all
select '23Z67-4R-C23' val from dual
)
select
val,
regexp_replace(val, '^[^-]+-(\d+)[LR].*', '\1')
from v_data
It matches
the beginning of the string "^"
one or more characters that are not a '-' "[^-]+"
followed by a '-' "-"
followed by one ore more digits (capturing them in a group) "(\d+)"
followed by 'L' or 'R' "[LR]"
followed by zero or more arbitrary characters ".*"