问题
I have a typical .json file for Chef e.g. servername.json
{
"name": "myserver123",
"chef_environment": "test",
"run_list": [
"role[base-pkg]",
"role[interesting_stuff]",
"role[user_apps]"
]
}
What I would like to do is use a "one liner" to add a new role after the last role found in the file. Since I never know what roles or how many are in a file i thought to search for the final closing "]"
bracket and add the new role above that.
I tried the following:
tac servername.json | sed -i '0,/\]/a "role[My_New_Role]"'
thinking that this would find the (now) first "]" and add the new line after it. However when I run the cmd it adds the line "role[My_New_Role]" 3 times. Twice before the "]"
and once in the correct place after the "]"
Questions:
1) Why is the line added 3 times when the "0" says match once ?
2) Would this be better done using AWK, Perl or Python (2.7.5) ? How ?
3) Should I use regex lookahead/behind instead of tac ?
4) Since I will need to process the file again to add a comma to the second to last role perhapes my whole approach is wrong ? What would be a better approach ?
回答1:
I don't know if this is the best approach (vs sed, AWK, or Perl) but it is straightforward to do what you're asking using python's json
library.
import json
# read the file as a dict using json.loads
d = json.loads(open('servername.json', 'r').read())
# add your new role to the end of the run_list
d['run_list'].append('role[My_New_Role]')
# write new json to file (specify a new file, or overwrite if you prefer)
open('new_servername.json', 'w').write(json.dumps(d, indent=2))
The output file looks like:
{
"chef_environment": "test",
"name": "myserver123",
"run_list": [
"role[base-pkg]",
"role[interesting_stuff]",
"role[user_apps]",
"role[My_New_Role]"
]
}
It's pretty easy to modify this code into a script with the filename as an input so that it's easy to run multiple times.
回答2:
Perl with the JSON
module:
cat servername.json | perl -MJSON -0 -ne '$j = decode_json($_); push @{$j->{run_list}}, q<role[My_New_Role]>; print encode_json($j)'
you can pretty-print it by replacing the print command with print to_json($j, {pretty => 1})
来源:https://stackoverflow.com/questions/47893288/add-a-new-role-to-a-chef-json-file-with-sed