As a_horse_with_no_name has already stated, the ideal here is to store this as an int and format on display, but I assume your system is the way it is for a reason, so.
The way to do this would be, in the select subquery of your insert statement: select the highest existing value, cast to int, increment, cast back to varchar, run through lpad, and then just in case no data exists yet, coalesce with '0001'.
insert into tab1 ("matri", "role", "libelle", "util")
select
tab2.matri,
coalesce((select lpad((role::integer + 1)::varchar, 4, '0') from tab1 order by role desc limit 1), '0001'),
'MANAGER',
E'MANAGER'
from
tab2
where
tab2.matri IN (select matri from tab2);
An alternative approach would be to create a trigger to do this for you, so you don't need to do this manually everywhere you insert into the table:
-- Create trigger function
create or replace function tg_fn_tab1_varchar_increment(
) returns trigger as $$
declare
_r varchar;
begin
select into _r
role
from
tab1
order by
role desc
limit 1;
if _r is null then
NEW.role := '0001';
return NEW;
end if;
NEW.role := lpad((_r::integer + 1)::varchar, 4, '0');
return NEW;
end;
$$ language plpgsql volatile;
-- Attach trigger
create trigger tg_tab1_varchar_increment before insert on tab1
for each row execute procedure tg_fn_tab1_varchar_increment();