如何从线路中捕获参数和值

如何从线路中捕获参数和值

我们只想捕获参数 -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

相关内容