使用 Perl 的列过滤器表达式的正确联机程序是什么?
What is the correct onliner for a column filter expression using Perl?
我尝试从 Linux 下的配置文件中过滤表达式,在管道中混合 bash 命令行工具和 Perl 命令。
我有一个配置文件(参见配置部分),可以使用 `
过滤相关行
grep PG.DATABASE database.conf | \
sed -r -e 's/^\s*//;s/\s+/ /' | \
cut -d ' ' -f2 | \
sort
并得到预期的结果:
DB.GRM.CON.LOCAL.V01
DB.GRM.CON.LOCAL.V02
DB.GRM.CON.LOCAL.V03
现在我想切换到 Perl
grep PG.DATABASE database.conf | \
perl -lpe 's/^\s*//; @m = split /\s+/; print $m[1]'
但是我得到了重复输入行的奇怪结果。
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
问题
为什么会出现重复?使用命令行工具获得的结果是否正确?
配置文件
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
我建议将 -p
选项(使其自动打印每一行)更改为 -n
。您也可以跳过 grep
,让 perl
执行:
perl -lne 'if(/PG\.DATABASE/) {chomp; s/^\s*//; @m = split /\s+/; print $m[1]}' database.conf
简化可以是:
perl -lne 'print if(/PG\.DATABASE:\s(\S+)/)' database.conf
您还可以让 perl 自动拆分成列,这可能是 在 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
但是你的格式并不是真正面向列的,所以我会像其他答案一样使用正则表达式捕获解决方案:
perl -lne 'print if(/^\s*PG\.DATABASE:\s*(\S+)/)' database.conf
我会做:
perl -nE 'say if /^\s+PG\.DATABASE:\s+(\S+)/' file
这在 GNU grep 中也有效:
grep -oP '^\s+PG\.DATABASE:\s+\K\S+' file
和 GNU sed:
sed -nE 's/^\s+PG\.DATABASE:\s+(\S+).*//p' file
或POSIX sed:
sed -nE 's/^[[:blank:]]*PG\.DATABASE:[[:blank:]]*([^[:blank:]]*).*//p' file
我尝试从 Linux 下的配置文件中过滤表达式,在管道中混合 bash 命令行工具和 Perl 命令。
我有一个配置文件(参见配置部分),可以使用 `
过滤相关行grep PG.DATABASE database.conf | \
sed -r -e 's/^\s*//;s/\s+/ /' | \
cut -d ' ' -f2 | \
sort
并得到预期的结果:
DB.GRM.CON.LOCAL.V01
DB.GRM.CON.LOCAL.V02
DB.GRM.CON.LOCAL.V03
现在我想切换到 Perl
grep PG.DATABASE database.conf | \
perl -lpe 's/^\s*//; @m = split /\s+/; print $m[1]'
但是我得到了重复输入行的奇怪结果。
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
问题
为什么会出现重复?使用命令行工具获得的结果是否正确?
配置文件
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
我建议将 -p
选项(使其自动打印每一行)更改为 -n
。您也可以跳过 grep
,让 perl
执行:
perl -lne 'if(/PG\.DATABASE/) {chomp; s/^\s*//; @m = split /\s+/; print $m[1]}' database.conf
简化可以是:
perl -lne 'print if(/PG\.DATABASE:\s(\S+)/)' database.conf
您还可以让 perl 自动拆分成列,这可能是 在 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
但是你的格式并不是真正面向列的,所以我会像其他答案一样使用正则表达式捕获解决方案:
perl -lne 'print if(/^\s*PG\.DATABASE:\s*(\S+)/)' database.conf
我会做:
perl -nE 'say if /^\s+PG\.DATABASE:\s+(\S+)/' file
这在 GNU grep 中也有效:
grep -oP '^\s+PG\.DATABASE:\s+\K\S+' file
和 GNU sed:
sed -nE 's/^\s+PG\.DATABASE:\s+(\S+).*//p' file
或POSIX sed:
sed -nE 's/^[[:blank:]]*PG\.DATABASE:[[:blank:]]*([^[:blank:]]*).*//p' file