我们只想捕获参数 -segment.bytes
及其值
例子
echo "$info" | grep "segment.bytes"
{"version":1,"config":{"segment.bytes":"10737555","retention.bytes":"104857600"}}
我的想法是删除所有单词,直到segment.bytes
并删除segment.bytes
包含值而不包含值双引号
预期结果示例
echo "$info" | grep "segment.bytes" | ......
segment.bytes:10737555
我试试这个
echo "$info" | grep "segment.bytes" | sed s'/"/ /g' | sed 's/^.*segment.bytes/segment.bytes/' | awk '{print $1":"$3}
我得到
segment.bytes:10737555
但我觉得我的方法可能很危险,因为获得价值的结果非常敏感的重要的是,可能会得到错误的结果灾难性的
我很乐意获得其他更可靠的选择
答案1
您可以尝试$info
通过此sed
调用管道传递变量:
echo "$info" | sed -E '/"segment\.bytes"/s/.*"(segment\.bytes)":"([^"]+)".*/\1:\2/'
它将查找具有模式的行"segment.bytes"
,并将segment.bytes
字符串和后面括号中的字符串("
为简单起见定义为“anything but”)提取到捕获组 1 和 2 中,并打印“capture group 1”,“:”,和“捕获组 2”。
(请注意,激活扩展正则表达式的选项可能会根据您的sed
版本而有所不同。-E
现在是 POSIX 标准,并且适用于当前的 GNU、MacOS 和 BSD sed
,但如果失败,请查阅有关如何激活 ERE 的手册页)
为了更有选择性,请尝试
sed -E '/"segment\.bytes":"[0-9]+"/s/.*"(segment\.bytes)":"([0-9]+)".*/\1:\2/'
在行搜索和值捕获部分中,它只接受整数值。
答案2
grep
调用之前不需要先调用sed
。
$ echo "$info"
foo
{"version":1,"config":{"segment.bytes":"10737555","retention.bytes":"104857600"}}
bar
$ echo "$info" | sed -n 's/.*"\(segment\.bytes\)":"\([^"]*\)".*/\1:\2/p'
segment.bytes:10737555
或者对于整行上的非常具体的匹配,使错误匹配的可能性几乎不可能,但显然对输入格式的变化更加敏感:
$ echo "$info" |
sed -n 's/^{"version":[0-9][0-9]*,"config":{"\(segment\.bytes\)":"\([0-9][0-9]*\)","retention\.bytes":"[0-9][0-9]*"}}$/\1:\2/p'
segment.bytes:10737555
上面的内容适用于任何 sed。
答案3
安全可靠的方法是jq
使用实用程序:
$ echo "$info" \
| grep -F '"segment.bytes"' \
| jq -r '.config | "segment.bytes:" + ."segment.bytes"'
重击:
parameter substitutions
我们从左右两端进行剪辑并提取segment.bytes属性的值。
name="segment.bytes"
var=${info#*\"${name}\":\"}
printf "%s:%s\n" "$name" "${var%%\"*}"'
另一种方法是,首先将 tye 信息字符串分割成逗号和大括号上的换行符,这样 grep 就可以发挥作用并从 grep 的输出中删除双引号:
$ echo "$info" \
| tr '{,}' '[\n*]' \
| grep '^"segment\.bytes"' \
| tr -d \"
将 Perl 与 JSON 模块结合使用
$ echo "$line" | grep -F '"segment.bytes"' \
| perl -MJSON -lne '$,=":";
my $k = "segment.bytes";
print $k, decode_json($_)->{config}{$k};
'
如果 JSON 模块不可用,您也可以这样做。在此,我们首先使用 sed 生成有效的 Perl 代码,然后通过 do 语句将其在 Perl 中实现。那么 json 对象 $j 是一个哈希引用,我们可以从中提取我们想要的键。
$ echo "$info" \
| sed \
-e '/"segmen\.bytes"/!d' \
-e 'y/:/,/;s/.*/$j=&;/' \
> ./foo.json
$ perl -I. -le '$,=":";
my $name = "segment.bytes";
do "foo.json" or die $!;
print $name, $j->{config}{$name};
'
awk 和 sed 非常不言自明
$ echo "$info" | grep -F segment.bytes \
| awk -F '"segment\\.bytes":"' '
{
t = $2
sub(/".*/, "", t)
$0 = FS t
gsub(/["\\]/, "")
}1'
$ echo "$info" | grep -F segment.bytes \
| sed -ne '
y/{,}/\n\n\n/
/^"segment.bytes"/!D
s/"//g;P
'
答案4
您可以使用下面的 awk 命令
echo "$info"|awk -F "," '/segment.bytes/{for(i=1;i<=NF;i++){if($i ~ /segment/){gsub("\"","",$i);print $i }}}'| sed "s/.*{//g"
输出
segment.bytes:10737555