我想建立一种做“某事”的最佳方法,并将其视为我的shell脚本库中的工具。
“Something”:解析一行文字,在分隔符后获取值,修剪周围的空格
$ lsb_release -d
Description: Ubuntu 12.10
我想要Ubuntu 12.10
(基本上是:
分隔符后面的内容)而不是其他内容,特别是没有周围的空格,包括换行符。
我无法决定:
1 awk
$ lsb_release -d | awk -F':[[:blank:]]*' '{print $2}'
Ubuntu 12.10
2 perl
$ lsb_release -d | perl -F':\s*' -lane 'print $F[1]'
Ubuntu 12.10
3 bash
$ v=$(lsb_release -d); printf "${v/*:[[:blank:]]/}\n"
Ubuntu 12.10
4其他的东西,写得更好,你可以在这里推荐
我正在寻找 pure 的东西,用自己选择的语言编写。
从这个角度来看,我在<{3}}能够提出的内容中感到特别失望,这是我正在努力研究的一种shell语言,但我无能为力。那。 ☹
我无法解释,例如,即使没有指定模式重复,替换也会替换多个空格,你可以吗?
你可能会提出比我的1.
,2.
和3.
更简洁优雅的方式 - 这太棒了。我有机会学习。
提问的理由:这些天我做了很多自学,我正在 Key: Value
格式的文本文件中保存信息..这真的有助于找到 伟大的 方法来获取第一个冒号后的内容。目前,文本配置文件是我能做的最好的。它会改变:)
PS:我迫不及待想要转移到bash,并且能够使用Commons Configuration(java)并移出我现在使用的这些Key: Value
格式。
能够简单地指定分隔符
分隔符后跟0..N空格(制表符,空格等)
解析出其余行并返回,没有新行
结果为单个字符串(即在http://commons.apache.org/proper/commons-configuration/中不是单独的字词)
答案 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的输出实际上比这里可以复制的更加丰富多彩。