PostgreSQL regexp_replace() to keep just one whitespace - regex

I need to clean up a string column with both whitespaces and tabs included within, at the beginning or at the end of strings (it's a mess !). I want to keep just one whitespace between each word. Say we have the following string that includes every possible situation :
mystring = ' one two three four '
2 whitespaces before 'one'
1 whitespace between 'one' and 'two'
4 whitespaces between 'two' and 'three'
2 tabs after 'three'
1 tab after 'four'
Here is the way I do it :
I delete leading and trailing whitespaces
I delete leading and trailing tabs
I replace both 'whitespaces repeated at least two' and tabs by a sole whitespace
WITH
t1 AS (SELECT' one two three four '::TEXT AS mystring),
t2 AS (SELECT TRIM(both ' ' from mystring) AS mystring FROM t1),
t3 AS (SELECT TRIM(both '\t' from mystring) AS mystring FROM t2)
SELECT regexp_replace(mystring, '(( ){2,}|\t+)', ' ', 'g') FROM t3 ;
I eventually get the following string, which looks nice but I still have a trailing whitespace...
'one two three four '
Any idea on doing it in a more simple way and solving this last issue ?
Many thanks !

SELECT trim(regexp_replace(col_name, '\s+', ' ', 'g')) as col_name FROM table_name;
Or In case of update :
UPDATE table_name SET col_name = trim(regexp_replace(col_name, '\s+', ' ', 'g'));
The regexp_replace is flags are described on this section of the documentation.

SELECT trim(regexp_replace(mystring, '\s+', ' ', 'g')) as mystring FROM t1;
Posting an answer in case folks don't look at comments.
Use '\s+'
Not '\\s+'
Worked for me.

It didn't work for me with trim and regexp_replace. So I came with another solution:
SELECT trim(
array_to_string(
regexp_split_to_array(' test with many spaces for this test ', E'\\s+')
, ' ')
) as mystring;
First regexp_split_to_array eliminates all spaces leaving "blanks" at the beginning and the end.
-- regexp_split_to_array output:
-- {"",test,with,many,spaces,for,this,test,""}
When using array_to_string all the ',' become spaces
-- regexp_split_to_array output ( '_' instead of spaces for viewing ):
-- _test_with_many_spaces_for_this_test_
The trim is to remove the head and tail
-- trim output ( '_' instead of spaces for viewing ):
-- test_with_many_spaces_for_this_test

Related

SQLite Pattern Matching with Extra Character

My database contains these rows:
DuPage
Saint John
What queries could I use that would match people entering either 'Du Page' or 'SaintJohn': in other words: adding an extra character (at any position) that shouldn't be there, or removing a character (at any position) that should be there?
The first example has a possible workaround: I could just remove the space character from the 'Du Page' input before searching the table, but I cannot do that with the second example unless there was some way of saying 'match 'SaintJohn' with the database text that has had all spaces removed', or alternatively 'match a database row that has every letter in 'SaintJohn' somewhere in the row.
Remove spaces from the column and the search text:
select * from tablename
where replace(textcolumn, ' ', '') like '%' || replace('<your search string>', ' ', '') || '%'

Split single row string into multiple rows by multi-chracter delimiter Oracle

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

Replacing space with ? In Informatica

I have a scenario where my Data looks like below
COLA
'XYZ'
'XYZ '
'ABC PQR'
'ABC PQR '
There are duplicates with same name but one have Space at the ending and then '
I want those space to be Replaced by '?' . So the data would look like
COLA
'XYZ'
'XYZ?'
'ABC PQR'
'ABC PQR?'
Please help with your suggestions
Should be simple IIF(SUBSTR (FIELD,-1) = ' ', RTRIM(FIELD) || '?', FIELD).
This assumes that even if you get multiple spaces at the end of one string you'd be happy to replace them all with just 1 ?.
Looks like another interview tricky question with no real-life application to me but...
IIF(RTRIM(COLA)=RTRIM(prev_COLA), RTRIM(COLA) || '?', COLA)
This assumes the data is sorted before the Expression Transformation and prev_COLA is a variable port having previous value of the COLA port.

Replace Leading and Trailing Spaces Oracle

I have a column in database table in Oracle having values with leading and trailing spaces. I would like the leading spaces to be replaced with 'P' and trailing spaces with 'T', using Inline Query only.
If you want to replace each leading/training space with an equal number of P/Ts then you can use:
SELECT REPLACE( REGEXP_SUBSTR( your_column, '^ +' ), ' ', 'P' )
|| TRIM( BOTH FROM your_column )
|| REPLACE( REGEXP_SUBSTR( your_column, ' +$' ), ' ', 'T' )
FROM your_table
If you want to replace the spaces with a single P/T then:
SELECT REGEXP_REPLACE(
REGEXP_REPLACE( your_column, '(.*?) +$', '\1T' ),
'^ +(.*)',
'P\1'
)
FROM your_table
Since you didn't specify if the amount of your leading and trailing spaces are all of a constant length, something like this could be used only if they are:
select replace(substr(' hello world ',1, instr(' hello world ',' ',1,2) ),' ','P')||
trim(' hello world ')||
replace(substr(' hello world ', instr(' hello world ',' ',-1,2), length(' hello world ') ),' ','T')
from dual;
Note that, the number "2" in all of the instr functions within the query, would represent the constant number of leading/trailing spaces, so you should change it to suit your need.

Teradata regexp_replace to eliminate specific special characters

I imported a file that contains email addresses (email_source). I need to join this table to another, using this field but it contains commas (,) and double quotes (") before and after the email address (eg. "johnsmith#gmail.com,","). I want to replace all commas and double quotes with a space.
What is the correct syntax in teradata?
Just do this:
REGEXP_REPLACE(email_source, '[,"]', ' ',1,0,i)
Breakdown:
REGEXP_REPLACE(email_source, -- sourcestring
'[,"]', -- regexp
' ', --replacestring
1, --startposition
0, -- occurrence, 0 = all
'i' -- match -> case insensitive
)
You don't need a regex for this, a simple oTranslate should be more efficient:
oTranslate(email_source, ',"', ' ')