使用 sed 和 jq 在 属性 中替换 json 项

Make replacements in a property of a json item using sed and jq

我有一个包含 json 项列表的文件(每行一个),如下所示:

{ name: "Bob", location: "Boston, MA" }
{ name: "Peter", location: "San Francisco, CA" }
{ name: "Jane", location: "New York City, NY" }

比方说,我想在位置 属性 中用 Massachussetts 替换 MA。我知道我可以使用 sed 's/MA/Massachussetts' 但这也会替换 name 字段中的每个 MA

有没有办法从命令行执行此操作,例如使用 jq

您可以试试下面的方法。

$ sed 's/\(\blocation: \+"[^,]*, *\)MA"/Massachussetts"/g' file
{ name: "Bob", location: "Boston, Massachussetts" }
{ name: "Peter", location: "San Francisco, CA" }
{ name: "Jane", location: "New York City, NY" }

$ sed 's/\(\blocation: \+"[^"]*\)\bMA/Massachussetts/g' file
{ name: "Bob", location: "Boston, Massachussetts" }
{ name: "Peter", location: "San Francisco, CA" }
{ name: "Jane", location: "New York City, NY" }

在当前 public 版本的 jq (1.4) 中,没有进行正则表达式替换的选项。然而,这将在下一个版本中改变。

sub 过滤器允许您对字符串进行正则表达式替换。然后你可以这样做:

.location |= sub("MA$"; "Massachussetts")

不过,您必须进行一些创造性操作才能允许多种选择。

这是一个解决方案,假设您的数据是干净的并且您需要的替换是有限的。

.location = (
   {
     "Boston, MA":        "Boston, Massachussettts",
     "San Francisco, CA": "San Francisco, California",
     "New York City, NY": "New York City, New York"
   }[.location] // .location
)

如果 filter.jq 包含上述过滤器并且 input.json 包含

{ "name": "Bob", "location": "Boston, MA" }
{ "name": "Peter", "location": "San Francisco, CA" }
{ "name": "Jane", "location": "New York City, NY" }
{ "name": "Unknown", "location": "Unknown" }

然后

jq -M -c -f filter.jq input.json

会产生

{"name":"Bob","location":"Boston, Massachussettts"}
{"name":"Peter","location":"San Francisco, California"}
{"name":"Jane","location":"New York City, New York"}
{"name":"Unknown","location":"Unknown"}

注意如果查找失败,使用 // 保持位置不变。