Reputation: 3941
{
"id": "a1234567-89ab-cdef-0123-456789abcdef",
"properties": {
...
"my_id": "c1234567-89ab-cdef-0123-456789abcdef",
...
}
Given the above in a file, I want to be able to perform a match (including the 4 leading spaces) on my_id
and then append a new line "my_value": "abcd",
. The desired output would look like this:
{
"id": "a1234567-89ab-cdef-0123-456789abcdef",
"properties": {
...
"my_id": "c1234567-89ab-cdef-0123-456789abcdef",
"my_value": "abcd",
...
}
Using examples online, I'm unable to get the command to work. Here is an example of something I have tried: sed '/.*"my_id".*/a "my_value": "abcd",' test.json
, for which I receive the following error: command a expects \ followed by text
.
What is the correct way to structure this command?
Upvotes: 2
Views: 771
Reputation: 58478
This might work for you (GNU sed):
sed '/"my-id".*/p;s//"my-value": "abcd"/' file
Match on "my-id"
and print that line, then substitute the additional line.
Upvotes: 1
Reputation: 204124
Using any awk:
$ awk -v new='"my_value": "abcd",' '{print} sub(/"my_id":.*/,""){print $0 new}' file
{
"id": "a1234567-89ab-cdef-0123-456789abcdef",
"properties": {
...
"my_id": "c1234567-89ab-cdef-0123-456789abcdef",
"my_value": "abcd",
...
}
The above will print the new line using whatever indent the existing "my_id"
line has, it doesn't assume/hard-code any indent, e.g. 4 blanks.
I'm using this:
sub(/"my_id":.*/,""){print $0 new}
instead of the briefer:
sub(/"my_id":.*/,new)
so it won't break if the new string contains any backreference chars such as &
.
Upvotes: 5
Reputation: 133650
With your shown samples and attempts please try following GNU awk
code. Where newVal
is an awk
variable having new value in it. Using match
function in GNU awk
where I have used regex (.*)("my_id": "[^"]*",)(.*)
which creates 3 capturing groups and saves values into an array named arr. Then printing values as per requirement.
awk -v newVal='"my_value": "abcd",' -v RS= '
match($0,/(.*)("my_id": "[^"]*",)(.*)/,arr){
print arr[1] arr[2] newVal arr[3]
}
' Input_file
Upvotes: 2
Reputation: 2687
awk
procedure with passed argument for insert value
The following awk
procedure allows for 'abcd'
to be passed as an argument for insertion (allowing it to be set in a bash script if required).
awk -v insertVal="abcd" '/"my_id":/{$0=$0"\n \"my_value\": \""insertVal"\","} {print}' dat.txt
explanation
The required insertion string ('abcd'
in this case) is passed as an argument using the -v
variable switch followed by a variable name and value: insertVal="abcd"
.
The first awk
action
block has a pattern
condition to only act on lines containing the target-line string (in this case "my_id":
). When a line with that pattern
is found, the line is extended with a new line mark \n
, the required four spaces to start the next line, the specified key
named "my_value"
, and the value associated with the key, passed by argument as the variable named insertVal
("abcd"
), and the final ,
character. Note the need to escape the "
quotes to render them.
The final awk
block, prints the current line (whether or not it was modified).
test
The procedure was tested on Mac Terminal using GNU Awk 5.2.0.
The output generated (from the input data saved to a file named dat.txt
) is:
{
"id": "a1234567-89ab-cdef-0123-456789abcdef",
"properties": {
...
"my_id": "c1234567-89ab-cdef-0123-456789abcdef",
"my_value": "abcd",
...
}
Upvotes: 2
Reputation: 11237
Using sed
$ sed -e '/my_id/{p;s/id.*"/value": "abcd"/' -e '}' input_file
{
"id": "a1234567-89ab-cdef-0123-456789abcdef",
"properties": {
...
"my_id": "c1234567-89ab-cdef-0123-456789abcdef",
"my_value": "abcd",
...
}
Upvotes: 3