Home > Enterprise >  What is the correct onliner for a column filter expression using Perl?
What is the correct onliner for a column filter expression using Perl?

Time:02-03

I try to filter expression from a configuration file under Linux mixing bash command line tools and Perl commands in a pipe.

I have a configuration file (see section configuration) and can filter the relevant lines by using `

grep PG.DATABASE database.conf | \
sed -r -e 's/^\s*//;s/\s / /'  | \
cut -d ' ' -f2 | \
sort

And get the result as expected:

DB.GRM.CON.LOCAL.V01
DB.GRM.CON.LOCAL.V02
DB.GRM.CON.LOCAL.V03

Now I want to switch to Perl

grep PG.DATABASE database.conf | \
perl -lpe 's/^\s*//; @m = split /\s /; print $m[1]'  

but I get strange results with a duplication of the input line.

DB.GRM.CON.LOCAL.V01
PG.DATABASE: DB.GRM.CON.LOCAL.V01 BEGIN
DB.GRM.CON.LOCAL.V02
PG.DATABASE: DB.GRM.CON.LOCAL.V02 BEGIN
DB.GRM.CON.LOCAL.V03
PG.DATABASE: DB.GRM.CON.LOCAL.V03 BEGIN

Question

Why is the duplication there and is the correct Perl oneliner for result achieved with the command line tools?

Configuration File

PG.CONFIG: DEFAULT BEGIN

   # Green Rebel Database via PG.SERVICE ------------------------
   PG.DATABASE: DB.GRM.CON.LOCAL.V01 BEGIN
     SERVICE:     'LOC-GRM-V0'
   END.DB.GRM.CON.LOCAL.V01

   # Green Rebel Database via DBI Driver ------------------------
   PG.DATABASE: DB.GRM.CON.LOCAL.V02 BEGIN
     DBI.PG: "dbi:Pg:dbname=grm;host=localhost;port=5432"
     AUTO.COMMIT: FALSE
     RAISE.ERROR: TRUE
     PRINT.ERROR: FALSE
   END.DB.GRM.CON.LOCAL.V02

   # Green Rebel Database via Host, Db, User, Pass --------------
   PG.DATABASE: DB.GRM.CON.LOCAL.V03 BEGIN
     SERVER:     'localhost'
     PORT:        5432
     DATABASE:    'grm'
     USER:        ${/SYSTEM/USER}
     SSL.MODE:    allow
     AUTO.COMMIT: FALSE
     RAISE.ERROR: TRUE
     PRINT.ERROR: FALSE
   END.DB.GRM.CON.LOCAL.V03
END.DEFAULT

CodePudding user response:

I suggest changing the -p option (which makes it automatically print every line) to -n. You can also skip the grep and let perl do it:

perl -lne 'if(/PG\.DATABASE/) {chomp; s/^\s*//; @m = split /\s /; print $m[1]}' database.conf

A simplification could be:

perl -lne 'print $1 if(/PG\.DATABASE:\s(\S )/)'  database.conf

CodePudding user response:

I would do:

perl -nE 'say $1 if /^\s PG\.DATABASE:\s (\S )/' file

Which also works in GNU grep:

grep -oP '^\s PG\.DATABASE:\s \K\S ' file

And GNU sed:

sed -nE 's/^\s PG\.DATABASE:\s (\S ).*/\1/p' file

Or POSIX sed:

sed -nE 's/^[[:blank:]]*PG\.DATABASE:[[:blank:]]*([^[:blank:]]*).*/\1/p' file

CodePudding user response:

You can also let perl do the splitting into columns automatically, that might be the correct way to filter columns in perl:

perl -lane 'print $F[1] if $F[0] eq "PG.DATABASE:"' database.conf
DB.GRM.CON.LOCAL.V01
DB.GRM.CON.LOCAL.V02
DB.GRM.CON.LOCAL.V03
  •  Tags:  
  • Related