用 jq 替换文件中的值(一行)

Ale*_*lex 1 shell-script jq

我想将“CTE_LG_LL_OE”的值从“警告”替换为“就绪”

{ "abcd": { "aav": "on", "vvg": "iio7890_APPID", "ct": "b-tte", "eSL": true, "it": "https://%ght%.mjk.com/", "tpo": "i-1", "pd": false, "pm": false, "pr": "" }, "en": { "CTE_LG_LL_OE": "warn", "S_G_EL_OD": "INFO", "G_LG_EL_OVE": "info" }, "EN_HTTPS": false }
Run Code Online (Sandbox Code Playgroud)

我可以使用以下命令在文件中找到相同的内容,但如何用一个衬垫命令替换它。

jq '.' /abc/temp/config.json | grep CTE_LG_LL_OE
Run Code Online (Sandbox Code Playgroud)

Kus*_*nda 8

要获取密钥的值,您可以使用 JSON 感知工具,例如jq而不是grep. 您这样做有几个原因:

  1. 您正在提取的值可能已被编码。jq如果您将其与-r( ) 选项一起使用,该工具将为您解码--raw-output。
  2. 使用时grep不区分值和键,因此您可能会意外提取不打算提取的数据。

CTE_LG_LL_OE提取顶级条目中键的值en:

jq -r '.en.CTE_LG_LL_OE' file
Run Code Online (Sandbox Code Playgroud)

将值设置为字符串ready并将结果文档写入文件new-file:

jq '.en.CTE_LG_LL_OE |= "ready"' file >new-file
Run Code Online (Sandbox Code Playgroud)

该|=运算符是“更新运算符”,它采用左侧键的“路径”和右侧键的新值。

要设置 shell 变量的值:

jq --arg newval "$newvalue" '.en.CTE_LG_LL_OE |= $newval' file >new-file
Run Code Online (Sandbox Code Playgroud)

这会创建一个从 shell 变量jq调用的变量,然后我们在表达式中使用它。变量中的值将自动由 .json 编码。$newvalnewvaluejqjq

为了便于阅读,请稍微间隔一下(假设这是 shell 脚本的一部分,因为问题被标记为):

jq --arg newval "$newvalue" \
    '.en.CTE_LG_LL_OE |= $newval' file >new-file
Run Code Online (Sandbox Code Playgroud)

对文件进行就地编辑(jq本身不支持就地编辑):

tmpfile=$(mktemp)

cp file "$tmpfile" &&
jq --arg newval "$newvalue" \
    '.en.CTE_LG_LL_OE |= $newval' "$tmpfile" >file &&
rm -f "$tmpfile"
Run Code Online (Sandbox Code Playgroud)

作为一次衬线:

tmpfile=$(mktemp); cp file "$tmpfile" && jq --arg newval "$newvalue" '.en.CTE_LG_LL_OE |= $newval' "$tmpfile" >file && rm -f "$tmpfile"
Run Code Online (Sandbox Code Playgroud)

如果您不确定该键在文档结构中的位置CTE_LG_LL_OE,并且只想更新具有该值的所有 键的值:CTE_LG_LL_OEwarn

jq '
    (
        .. |
        select(type == "object" and .CTE_LG_LL_OE? == "warn").CTE_LG_LL_OE
    ) |= "ready"' file
Run Code Online (Sandbox Code Playgroud)

这会递归地检查整个文档中的所有键和值。它找到所有具有CTE_LG_LL_OE带有 evalue 的键的对象warn,并将它们更新为ready。换行符只是为了可读性。

该值可以像以前一样从 shell 变量中获取:

jq --arg newval "$somevariable" '
    (
        .. |
        select(type == "object" and .CTE_LG_LL_OE? == "warn").CTE_LG_LL_OE
    ) |= $newval' file
Run Code Online (Sandbox Code Playgroud)

显然,这也可以与就地编辑相结合,如本答案的前半部分所示。

  • @Alex如果你愿意编写不可读的代码,几乎任何shell命令,无论多么复杂,都可以写在一行上。另外,为什么要在 shell 脚本中编写“one-liners”? (3认同)