我查看了其他答案,但无法获得如何执行此操作的正确解释。
我有一个名为 的字符串id
变量id='{"name":"john"}'
。我怎样才能从这个字符串中得到两个变量,比如-
key="name"
value="john"
详细的解释将不胜感激,因为我想了解 bash 中的字符串解析。
到目前为止,我已经{}
从字符串中删除了大括号 -
id="$( echo "${id}" | tr -d {} )"
我不能包含"
在那里,因为它会引发错误。还在寻找类似的东西,id.split(":")
最后得到一个数组。
答案1
您确实要求这样做understand string parsing in bash
,所以我会牢记这一点来写一个答案,即使这是您的问题的解决方案错误。你可以使用 bash 本身来做你想做的事情,如果你有真的很干净没有特殊字符的数据,其中特别的被定义为 之外的任何内容[A-Za-z0-9 ]
:
$ id='{"name":"john"}'
$ id="${id#*\{}" # remove everything through the first '{'
$ echo $id
"name":"john"}
$ id="${id%\}*}" # remove everything starting with the last '}'
$ echo $id
"name":"john"
$ name="${id%:*}" # take everything before the ':'
$ name="${name//\"/}" # remove quotes
$ echo $name
name
$ value="${id#*:}" # take everything after the ':'
$ value="${value//\"/}" # remove quotes
$ echo $value
john
这在“参数扩展”中都有描述bash手册。例如,${parameter#word}
这将从 的开头Remove matching prefix pattern
删除文本。同样,删除后缀。将出现的所有字符串替换为其后的内容(在上面的示例中,引号(必须转义,因此显示为)被替换为空字符串)。不过,您必须单独执行每个替换:您不能去掉开头word
$parameter
%
//
${foo//\"/}
\"
和用一个命令结束字符串。
您可能还注意到,您需要转义特殊字符,例如}
、{
和"
。只要你记得做对,你就可以写这样的代码很容易编写,但尽管很简单,但它正趋向于只写代码。当您在一两年内回到这段代码并重新使用它时,您会看到类似的内容#*\{}
并自言自语,这到底是什么意思?然后只是盲目地将其复制到新项目中,然后您的代码就会以微妙的方式崩溃,因为它遇到了您没有预料到的特殊字符。
如果您的名称/值对中包含特殊字符(例如大括号或转义引号或冒号或可能的其他字符),上面的示例将会中断。因此,这对于一些快速而肮脏的抓取或 80% 的用例来说效果很好,但你真的不应该在生产中或任何需要确保它始终适用于任何输入的时候使用它。
即使没有echo
其中的语句来向您展示发生了什么,您也可以看到此代码已经比其他答案中展示如何正确执行此操作的示例更长。因此,如果不使用第三方工具,您就会需要编写更多代码,这将花费您更长的时间来编写和调试,而且您最终也会得到一个不太灵活的解决方案,并且将要当遇到意想不到的事情时就会崩溃。
答案2
使用jq
:
id='{"name":"john"}'
key=$(jq -r keys[] <<<"$id")
value=$(jq -r .[] <<<"$id")
-r
:使用此选项,如果过滤器的结果是字符串,那么它将直接写入标准输出,而不是格式化为带引号的 JSON 字符串。
keys
:内置函数键,当给定一个对象时,会在数组中返回其键。
使用json
:
id='{"name":"john"}'
key=$(json -ak <<<"$id")
value=$(json -a "$key" <<<"$id")
-a
将输入处理为数组
-k
返回键值
答案3
或者,您可以使用基于步行路径的 UNIX 实用程序 jtc
:
id='{"name":"john"}'
bash $ key=$(jtc -w'[0]<>k' <<<"$id")
bash $ echo $key
"name"
bash $ value=$(jtc -w'[0]' <<<"$id")
bash $ echo $value
"john"
bash $
jtc
PS> 披露:我是用于 JSON 操作的 -shell cli 工具的创建者