linux处理工具(json)
jq处理样例
jq '.[0]' data.json 取每行数组的第一个元素
jq -c '.[0]' 取每行数组的第一个元素,紧凑输出,不进行格式化
jq 'max_by(length)' 取每行数组的最大长度的元素
工具使用1
结合前面的上下文,你的需求是将提取出的“最长数组”替换掉目标脚本中的某个固定字符串。在 Linux 中,处理这种包含特殊字符(如 JSON 中的 [、"、,)的替换任务,最稳健且高效的方法是使用 jq 配合 --argjson 参数,或者使用 sed。
这里有两种主要场景,取决于你的“目标脚本”是纯文本配置文件还是 JSON 配置文件。
🛠️ 场景一:目标文件是 JSON 格式(推荐)
如果你的目标脚本是一个 JSON 文件(例如 config.json),你想把其中某个字段(例如 "items": [])的值替换成刚才提取的最长数组。
假设:
- 源文件 (
data.json):包含每行的数组数据。 - 目标文件 (
config.json):{ "name": "my_script", "items": ["placeholder"] }
命令:
# 1. 先从 data.json 提取每行最长的数组
# 2. 使用 jq 的 --argjson 将提取结果作为变量传入
# 3. 修改 config.json 并覆盖原文件 (使用临时文件防止损坏)
jq --argjson new_array "$(jq -c 'max_by(length)' data.json)" \
'.items = $new_array' \
config.json > config.json.tmp && mv config.json.tmp config.json
原理解析:
jq -c 'max_by(length)' data.json:提取最长数组,-c确保输出为紧凑的一行,适合作为变量。--argjson new_array "...":将提取出的 JSON 字符串解析为真正的 JSON 对象,赋值给变量$new_array。这比字符串拼接更安全,不用担心引号转义问题。.items = $new_array:将目标文件中的.items字段替换为该变量。
📝 场景二:目标文件是普通文本(如 Shell 脚本、Python 脚本)
如果你的目标是一个 .sh 或 .py 文件,里面有一行固定的字符串(例如 MY_ARRAY=[]),你想把 [] 里的内容替换掉。
假设:
- 目标脚本 (
script.sh):#!/bin/bash MY_ARRAY=["old", "data"] echo "Running..."
方法 A:使用 sed (简单直接)
# 提取最长数组并转为字符串(去掉换行符)
NEW_VAL=$(jq -c 'max_by(length)' data.json)
# 使用 sed 替换
# 注意:这里假设旧值是 ["old", "data"],我们将其替换为 $NEW_VAL
sed -i "s/MY_ARRAY=$$.*$$/MY_ARRAY=${NEW_VAL}/" script.sh
⚠️ 风险提示:
如果提取出的数组中包含 / 符号(例如文件路径),sed 的默认分隔符 / 会报错。为了安全,建议使用 | 或其他符号作为分隔符:
sed -i "s|MY_ARRAY=.*|MY_ARRAY=${NEW_VAL}|" script.sh
方法 B:使用 jq 处理文本文件 (最安全)
如果你的脚本内容很复杂,怕 sed 搞坏格式,可以用 jq 把整个脚本当成一个字符串来处理。
NEW_VAL=$(jq -c 'max_by(length)' data.json)
# 将整个文件读入,用正则替换,再输出
jq -Rs --argjson val "$NEW_VAL" '
gsub("MY_ARRAY=\$$.*\$$"; "MY_ARRAY=$$val | tojson)")
' script.sh > script.sh.tmp && mv script.sh.tmp script.sh
🔄 场景三:多对多替换(批量处理)
如果你的意思是:源文件有 10 行,目标脚本也有 10 行,要把源文件第 1 行的最长数组替换目标脚本第 1 行的占位符,以此类推。
这需要用到 paste 命令将两个文件合并流,然后处理。
命令:
# 1. 准备源数据(提取每行最长数组)
# 2. 使用 paste 将 目标脚本 和 源数据 并排合并
# 3. 使用 jq 读取两列数据并组合
paste script.sh <(jq -c 'max_by(length)' data.json) | \
jq -Rs '
split("\n") |
map(
split("\t") |
if length == 2 then
(.[0] | gsub("PLACEHOLDER"; .[1]))
else .[0] end
) |
join("\n")
' > script_new.sh
📌 总结建议
- 如果是改 JSON 配置:请务必使用 场景一 (
--argjson),这是最标准、不出错的方法。 - 如果是改 代码脚本:推荐使用 场景二的方法 A,但要注意特殊字符转义。
工具使用2
paste 命令本身并不能直接通过管道符 | 将内容传给 jq,因为 paste 的输出是纯文本,而 jq 需要处理的是 JSON 格式的数据。
但是,你可以通过一个巧妙的组合,利用 paste 生成 JSONL (JSON Lines) 格式的数据,再将其作为数组输入给 jq 进行处理。
这个组合的核心是 jq 的 -s (或 --slurp) 选项。它的作用是将输入的多个 JSON 对象“ slurp ”成一个大的 JSON 数组。
🎯 核心思路
- 使用
paste将多个文件的内容按行合并,并用自定义分隔符(如逗号)连接。 - 通过管道将
paste的输出传递给jq。 - 在
jq中使用-s选项读取所有输入行,并将每一行构造成一个 JSON 对象。
🛠️ 具体操作
假设你有两个文件:
- names.txt
Alice Bob Charlie - ages.txt
25 30 35
你的目标是将它们合并成一个 JSON 数组:
[{"name": "Alice", "age": "25"}, {"name": "Bob", "age": "30"}, {"name": "Charlie", "age": "35"}]。
你可以使用以下命令:
paste -d ',' names.txt ages.txt | jq -s 'map({name: ., age: .})'
命令分解
-
paste -d ',' names.txt ages.txt- 这部分命令会将两个文件按行合并,并用逗号
,作为分隔符。 - 输出结果是三行文本:
Alice,25 Bob,30 Charlie,35
- 这部分命令会将两个文件按行合并,并用逗号
-
|- 管道符将上一步
paste的文本输出作为下一步jq命令的输入。
- 管道符将上一步
-
jq -s 'map({name: ., age: .})'-s: 这个选项告诉jq读取所有输入行。由于输入是纯文本,jq会自动将每一行当作一个字符串。-s会将这些字符串放入一个数组中,例如:["Alice,25", "Bob,30", "Charlie,35"]。map(...): 这是一个jq函数,它会对数组中的每一个元素执行括号内的操作。{name: ., age: .}: 这是map内部的操作。对于数组中的每个字符串(如"Alice,25"),jq会自动根据逗号将其分割成一个子数组(如["Alice", "25"])。.取子数组的第一个元素(名字)。.取子数组的第二个元素(年龄)。- 最后,将这些值构造成一个新的 JSON 对象。
最终,map 函数将所有新生成的 JSON 对象收集起来,形成你想要的 JSON 数组。

浙公网安备 33010602011771号