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

用 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 }

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

jq '.' /abc/temp/config.json | grep CTE_LG_LL_OE

答案1

得到键的值,您将使用 JSON 感知工具,例如jq而不是grep.您这样做有几个原因:

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

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

jq -r '.en.CTE_LG_LL_OE' file

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

jq '.en.CTE_LG_LL_OE |= "ready"' file >new-file

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

要设置 shell 变量的值:

jq --arg newval "$newvalue" '.en.CTE_LG_LL_OE |= $newval' file >new-file

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

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

jq --arg newval "$newvalue" \
    '.en.CTE_LG_LL_OE |= $newval' file >new-file

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

tmpfile=$(mktemp)

cp file "$tmpfile" &&
jq --arg newval "$newvalue" \
    '.en.CTE_LG_LL_OE |= $newval' "$tmpfile" >file &&
rm -f "$tmpfile"

作为一次衬线:

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

如果您不确定在哪里在文档结构中,CTE_LG_LL_OE键位于并且只想更新值全部 CTE_LG_LL_OE具有值的键warn

jq '
    (
        .. |
        select(type == "object" and .CTE_LG_LL_OE? == "warn").CTE_LG_LL_OE
    ) |= "ready"' file

这会递归地检查整个文档中的所有键和值。它找到所有具有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

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

答案2

对于 file.json 中的示例内容,以下单行代码有效:

cat file.json | jq '.en.CTE_LG_LL_OE = "ready"' | tee file.json

分解一下:

  1. cat …将 file.json 的内容复制到标准输出 (stdout)。
  2. |将此输出发送到下一个命令的标准输入 (stdin)。
  3. jq '.en.CTE_LG_LL_OE = "ready"'具有 jq 所谓的“过滤器”('.en.CTE_LG_LL_OE = "ready"'将特定值分配给特定键),但确实不是指定任何输入文件。这会导致jq从标准输入读取其输入。
  4. | tee将输出发送jqtee命令,该命令将其写入标准输出指定的文件。

我对自己的行为感到困惑后发现了这个问题jq。由于某种原因(比较答案https://stackoverflow.com/questions/48964305/write-output-to-a-file-after-piped-to-jq) 输出重定向不是工作,jq文件也不会自行读取。简而言之,以下都不起作用;其中任何一个都会截断 file.json,使其完全为空:

jq '.en.CTE_LG_LL_OE = "ready"' file.json >file.json

jq '.en.CTE_LG_LL_OE = "ready"' file.json | tee file.json

cat file.json | jq '.en.CTE_LG_LL_OE = "ready"' >file.json

某些标准命令行选项可能会改变此行为。

相关内容