Reputation: 22653
Is there a way how to split string after every nth character in PostgreSQL? I thought regexp_split_to_array
can be used to do this:
select unnest(regexp_split_to_array('abcdefgh', E'...regexp here...'));
Example input: abcdefgh
Required output (split after every 2nd character):
ab
cd
ef
gh
Required output (split after every 3rd character):
abc
def
gh
What regexp will do this? Is there any other solution?
Upvotes: 11
Views: 7619
Reputation: 324511
Use substring
and generate_series
:
regress=> select substring('abcdefgh' from n for 2) from generate_series(1, length( 'abcdefgh' ), 2) n;
substring
-----------
ab
cd
ef
gh
(4 rows)
regress=> select substring('abcdefgh' from n for 3) from generate_series(1, length( 'abcdefgh' ), 3) n;
substring
-----------
abc
def
gh
(3 rows)
This is trivially wrapped into an inlineable SQL function:
CREATE OR REPLACE FUNCTION string_nchars(text, integer) RETURNS setof text AS $$
SELECT substring($1 from n for $2) FROM generate_series(1, length($1), $2) n;
$$ LANGUAGE sql IMMUTABLE;
Usage:
regress=> SELECT string_nchars('abcdefgh',3);
string_nchars
---------------
abc
def
gh
(3 rows)
Upvotes: 15
Reputation: 44227
You can use lookaheads. Lookbehind would be better, but are not implemented.
This only works if the length of the string is even (or a multiple of the split size), and might be inefficient for large strings.
select unnest(regexp_split_to_array('abcdefgh', E'(?=(..)+$)'));
If it is not a multiple, then something like:
select reverse(unnest) from unnest(regexp_split_to_array(reverse('abcdefgh'), E'(?=(...)+$)'));
But I'd probably install plperl and then do it in Perl.
Upvotes: 6