考虑一个包含对的文件key=value
,每个文件都可以是多个skey
的串联。key
换句话说,许多key
s 可以映射到一个value
。这背后的原因是,key
与 的长度相比,每个字都是相对较短的字value
,因此数据被“压缩”成更少的行。
插图(即不是真实值):
$ cat testfile
AA,BB,CC=a-lengthy-value
A,B,C=a-very-long-value
D,E,F=another-very-long-value
K1,K2,K3=many-many-more
Z=more-long-value
假设所有key
s 都是唯一的并且不包含以下字符是有效的:
key
分隔符:,
- 键值分隔符:
=
- 空白字符:
key
s 可以以任何形式出现未来(在上述约束条件下),他们现在同时遵守以下正则表达式:[[:upper:]]{2}[[:upper:]0-9]
.同样,value
s 不会包含=
,因此=
可以安全地用于分割每一行。没有多行key
或多value
行,因此逐行处理也是安全的。
为了方便从该文件中提取数据,getval()
定义了一个函数:
getval() {
sed -n "/^\([^,]*,\)*$1\(,[^=]*\)*=\(.*\)$/{s//\3/p;q}" testfile
}
因此,调用getval A
将返回值a-very-long-value
,而不是a-lengthy-value
。对于不存在的 ,它也应该不返回任何内容key
。
问题:
- 当前的鲁棒定义
getval()
足够吗? - 是否有其他可能更短/更具表现力/更具限制性的数据提取方法?
无论如何,这个脚本将与 cygwin 一起运行,bash
并且coreutils
它附带了。因此,这里不需要可移植性(即仅给出加分)。谢谢!
编辑:
更正了功能,添加了有关按键的说明。
编辑2:
添加了有关格式(无多行)和可移植性(不是要求)的说明。
答案1
您可以使用以下方法以更易读的形式编写它awk
:
getval() {
awk -F'=' '$1~/\<'"$1"'\>/{print $2}' testfile
}
答案2
和sed
...
getval() { sed "/^\([^=]*,\)*$1[,=]/!d;s/.*=//;q"; } <infile
不过,您可能想要验证$1
输入。
或者使用 GNUgrep
和cut
:
getval() { grep -Em1 "^([^=]*,)*$1[,=]" | cut -d= -f2-; } <infile