解析文本,在`:`冒号后选择值,修剪周围的空格

时间:2013-04-02 23:36:45

标签: perl bash awk

我想建立一种做“某事”的最佳方法,并将其视为我的shell脚本库中的工具。

“Something”:解析一行文字,在分隔符后获取值,修剪周围的空格


实施例

$ lsb_release -d
Description:    Ubuntu 12.10

我想要Ubuntu 12.10(基本上是:分隔符后面的内容)而不是其他内容,特别是没有周围的空格,包括换行符。


我无法决定:

1

$ lsb_release -d | awk -F':[[:blank:]]*' '{print $2}'
Ubuntu 12.10

2

$ lsb_release -d | perl -F':\s*' -lane 'print $F[1]'
Ubuntu 12.10

3

$ v=$(lsb_release -d); printf "${v/*:[[:blank:]]/}\n"
Ubuntu 12.10

4其他的东西,写得更好,你可以在这里推荐


我正在寻找 pure 的东西,用自己选择的语言编写。

从这个角度来看,我在<{3}}能够提出的内容中感到特别失望,这是我正在努力研究的一种shell语言,但我无能为力。那。 我无法解释,例如,即使没有指定模式重复,替换也会替换多个空格,你可以吗?

你可能会提出比我的1.2.3.更简洁优雅的方式 - 这太棒了。我有机会学习。


提问的理由:这些天我做了很多自学,我正在 Key: Value 格式的文本文件中保存信息..这真的有助于找到 伟大的 方法来获取第一个冒号后的内容。目前,文本配置文件是我能做的最好的。它会改变:)


PS:我迫不及待想要转移到,并且能够使用Commons Configuration()并移出我现在使用的这些Key: Value格式。


假设:

5 个答案:

答案 0 :(得分:4)

虽然我亲自将awk作为此类事物的第一手段,但您在那里使用的代码可能并不像您所希望的那样通用。特别是,通过设置字段分隔符,您可能会在属性行的右侧识别它,这使得$2实际上不是完整的属性值。我认为你可能最好避免使用FS并做类似下面的事情,它在完整的原始行上运行:

awk '{ sub(/^[^:]*:[:blank:]*/, ""); print }'

这是稍微缩写的版本:

awk '{ sub(/^[^:]*:[:blank:]*/, "", $0); print $0; }'

也就是说,从行($0)中删除(用空字符串替换)所有内容,直到第一个冒号后跟零或多个空格。打印结果。

对于bash版本,我将使用[[表达式中提供的匹配运算符。你必须用于提取的子表达式的变量名有点冗长,但我喜欢我可以使用较少的古怪(或至少是通常预期的)正则表达式语法:

[[ $v =~ ^[^:]*:[:blank:]*(.*) ]] && echo "${BASH_REMATCH[1]}"

这里的正则表达式与上面awk版本中的正则表达式大致相同。

答案 1 :(得分:3)

另一个Perl版本:

lsb_release -d | perl -pe 's/^[^:]*:\s*//;s/\s*$//;'

答案 2 :(得分:1)

Perl有一个module available来解析Commons配置文件。作为(过度设计)单线:

lsb_release -d | perl -MConfig::Properties::Commons -E'say Config::Properties::Commons->new(load_file=>\*STDIN)->get_property("Description")'

作为普通脚本:

#!perl
use strict; use warnings; use 5.010;

use Config::Properties::Commons;

my $cpc = Config::Properties::Commons->new;
$cpc->load($ARGV[0] // \*STDIN);

say $cpc->get_property("Description");

如果没有该模块,我会使用split

split /:\s*/, $_将拆分任何冒号并删除所有后续空格,
split /:\s*/, $_, 2会将字符串分成两部分(因此值可以包括冒号),
并且(split /:\s*/, $_, 2)[1]将返回第二个片段。因此

lsb_release -d | perl -lne's/\s*$//, print for (split /:\s*/, $_, 2)[1]'

也可以。

答案 3 :(得分:1)

我想这仍然可以被视为一个单行:

lsb_release -d|php -r "echo trim(end(explode(':', file_get_contents('php://stdin'), 2)));"

遗憾的是,PHP没有简写来处理从stdin; - )

的提取

答案 4 :(得分:1)

如果你真的希望像你描述的那样解析文本,你可以使用YAML::XS

$ lsb_release -d | perl -MYAML::XS -E'local $/;say Load(<>)->{Description}'
Ubuntu 12.04.2 LTS
$ perl -MYAML::XS -MData::Printer -E'p Load(do{local $/;<>})'
key1: value1
key2: value2
^d
\ {
    key1   "value1",
    key2   "value2"
}

^d代表按 Ctrl + d

Data::Printer的输出实际上比这里可以复制的更加丰富多彩。