I have an export from postgresql table with multiple fields, including boolean (exported by postgresql as t
and f
character), and I need to import it in another database (monetdb) that won't understand t/f as bool values.
(EDIT removed spaces to reflect true file aspect and avoid angry comments - previously there was spaces displayed)
id|val_str|bool_1|bool2|bool_3|bool4|
1|help|t|t|f|t|
2|test|f|t|f|f|
...
As I cannot replace all occurence of t
/f
I need to integrate the field separator in my pattern.
I tried to use awk
to replace fields t
with TRUE
and f
with FALSE
:
awk -F'|' '{gsub(/\|t\|/, "|TRUE|"); gsub(/\|f\|/, "|FALSE|"); print;}'
This is working partially, as consecutive fields with a same value (|t|t|
) will have only the first occurrence replaced (|TRUE|t|
- as 2nd occurence is in fact t|
and not |t|
).
id|val_str|bool_1|bool2|bool_3|bool4|
1|help|TRUE|t|FALSE|TRUE|
2|test|FALSE|TRUE|FALSE|f|
...
Table has ~450 columns so I can't really specify the list of columns to be replaced, nor work in postgres to 'transform' boolean columns (I could but ...).
I could run the gsub()
twice, but I was looking for more elegant way to match the entire field content for all fields.
gsub(/^t$/, ...)
is not helping either as we are in the middle of a line most of the time.
if
perl
is okay, you can use lookarounds:\|\K
positive lookbehind to match|
\h*
optional horizontal space, remove if not actually present in input(?=\|)
positive lookahead to match|
Can also use looping with
sed
. Tested onGNU sed 4.2.2
, syntax may vary with other implementations:a
labels/| *t *|/| TRUE |/
substitute commandta
branch to labela
as long as substitute command succeeds:b
With no spaces in input
Use
sed
, it`s standard.sed 's/| *t */| TRUE /g;s/| *f */| FALSE /g'
This tells
sed
to substitute every substring that begins with a pipe character, an unknown number of spaces (maybe zero),t
and a space followed by an unknown number of spaces with| TRUE
; same withf
.Pipe the output through
column -t
if line lengths get messed up.You can let Postgres do the work for you. Basic query to produce the
SELECT
list:Produces a string of the form:
All identifiers are escaped properly. Columns are in default order. Copy and execute it. Use
COPY
to export to file. (Or\copy
in psql.) Performance is about the same as exporting a plain table. If you don't need upper case omitupper()
.Why is a simple cast to
text
enough?About
regclass
and escaping identifiers properly:If you need a complete statement with
TRUE
/FALSE
/NULL
in upper case, standard SQL cast notation (without colons::
), still original column names and maybe a schema-qualified tablename:Produces a complete statement of the form:
Assuming (based on your comments) that your input file actually doesn't look like the sample you posted but instead looks like this:
then all you need is:
with the general solution for N replacement strings being: