Reputation:
I am facing a situation that drives me nuts. I am setting up an update server which uses a json file. Don't ask why or how, it sucks and is my only possibility to achieve it.
I have been trying and researching for HOURS (many) because I went ballistic and wanted to crack this on my own. But I have to realize I got stuck and need help.
So sorry for this chunk but I think it is somewhat important to see...
The file is a one liner and repeating the following sequence with changing values (of course).
"plugin_name_foo_bar": {"buildDate": "bla", "dependencies": [{"name": "bla", "optional": true, "version": "1.00"}], "developers": [{"developerId": "bla", "email": "[email protected]", "name": "Bla bla2nd"}], "excerpt": "some text {excerpt} !bla.png|thumbnail,border=1! ", "gav": "bla", "labels": ["report", "scm-related"], "name": "plugin_name_foo_bar", "previousTimestamp": "bla", "previousVersion": "1.0", "releaseTimestamp": "bla", "requiredCore": "1", "scm": "github.com", "sha1": "ynnBM2jWo25ZLDdP3ybBOnV/Pio=", "title": "bla", "url": "http://bla.org", "version": "1.0", "wiki": "https://bla.org"}, "Exclusion": {"buildDate": "bla", "dependencies": [],
and the next plugin block is glued straight afterwards.
What I now want to do is to search for "plugin_foo_bar": {"
as this is the unique identifier for a new plugin description block.
I want to replace the first sha1 value occuring afterwards. That's where I keep failing. I always grab the first,last or any occurrence in the entire file and not the block :(
"title"
is the unique identifier after the sha1 value.
So I tried to make the .* less greedy but it ain't working out.
last attempt was heading towards:
sed -i 's/("name": "plugin_name_foo_bar.*sha1": ")([a-zA-Z0-9!@#\$%^&*()\[\]]*)(", "title"\)/\1blablabla\2/1'
default.json
to find the sha1 value of that plugin but still no joy. I hope someone knows - preferably a simpler approach - before I now continue with trial and error until I have to puke and freakout.
I am working with SED on Windows, so Unix approach might help me to figure out how to achieve this in batch but please make it as one-liner if possible. Scripts are a real pain to convert.
And I just need SED and no other solution with other tools like AWK. That is absolutely out of discussion.
Any help is appreciated :)
Cheers Jan
Upvotes: 1
Views: 1185
Reputation: 37569
sed -r "s/(plugin_name_foo_bar[^!]+sha1.: .)[^\"]+/\1abcdefghijkl/" file
Upvotes: 0
Reputation: 70923
For windows command line, with escaped quotes, replacing inline and using regular expression
sed -i -r "s/(plugin_name_foo_bar.+?sha1\": \")[^\"]+\"/\1abcdefghijkl\"/" default.json
Upvotes: 0
Reputation: 60235
As sputnick points out parsing is a little beyond what sed's meant for. Still, sed's Turing-complete and bludgeoning it into doing what you want can satisfy that {sad,masoch}istic urge so many of us feel from time to time.
This one's even easy.
sed '
s/"sha1": /\n/g
s/\("name": "plugin_name_foo_bar"[^\n]*\n"\)[^"]*/\1thenewsha/
s/\n/"sha1": /g
'
Upvotes: 0
Reputation: 184965
Don't use regex (sed) to parse JSON, instead use a proper JSON parser, or javascript directly like I do :
Using javascript and nodejs in a script :
File /tmp/file.json
is :
{
"plugin_name_foo_bar" : {
"excerpt" : "some text {excerpt} !bla.png|thumbnail,border=1! ",
"dependencies" : [
{
"name" : "bla",
"version" : "1.00",
"optional" : true
}
],
"title" : "bla",
"previousTimestamp" : "bla",
"releaseTimestamp" : "bla",
"sha1" : "ynnBM2jWo25ZLDdP3ybBOnV/Pio=",
"labels" : [
"report",
"scm-related"
],
"buildDate" : "bla",
"version" : "1.0",
"previousVersion" : "1.0",
"name" : "plugin_name_foo_bar",
"scm" : "github.com",
"url" : "http://bla.org",
"gav" : "bla",
"developers" : [
{
"email" : "[email protected]",
"developerId" : "bla",
"name" : "Bla bla2nd"
}
],
"wiki" : "https://bla.org",
"requiredCore" : "1"
},
"Exclusion" : {
"dependencies" : [],
"buildDate" : "bla"
}
}
The script script.js
:
var js = require('/tmp/file.json')
js.plugin_name_foo_bar.sha1 = "xxx"
console.log(js)
Usage :
nodejs script.js
Upvotes: 1