In general here is no robust way to fix this, nor to ignore any part of the row nor even to ignore the whole row because if a quoted string can contain quotes and can also contain :s and ,s then a messed up string can look exactly like a valid set of fields.
Having said that, if we target only the "name" field and assume that the associated string cannot contain ,s then with GNU awk for the 3rd arg to match() we can do:
$ cat tst.awk { while ( match($0,/(.*"name":")(([^,"]*"[^,"]*)+)(".*)/,a) ) { gsub(/"/,"",a[2]) $0 = a[1] a[2] a[4] } print }
$ awk -f tst.awk file {"user": "[email protected]","contact":[{"name":"Jack O'Malley","number":"+1 23456789"},{"name":"Jack Jill Smith-Jones","number":"+1 232324789"}]} {"user": "[email protected]","contact":[{"name":"X Æ A-12 Musk","number":"+1 23456789"},{"name":"Jack Jill","number":"+1 232324789"}]}
I ran the above on this input file:
$ cat file {"user": "[email protected]","contact":[{"name":"Jack "O'Malley","number":"+1 23456789"},{"name":"Jack "Jill "Smith-Jones","number":"+1 232324789"}]} {"user": "[email protected]","contact":[{"name":"X Æ A-12 "Musk","number":"+1 23456789"},{"name":"Jack Jill","number":"+1 232324789"}]}
and you can do the same using any awk:
$ cat tst.awk { while ( match($0,/"name":"([^,"]*"[^,"]*)+"/) ) { tgt = substr($0,RSTART+8,RLENGTH-9) gsub(/"/,"",tgt) $0 = substr($0,1,RSTART+7) tgt substr($0,RSTART+RLENGTH-1) } print }
$ awk -f tst.awk file {"user": "[email protected]","contact":[{"name":"Jack O'Malley","number":"+1 23456789"},{"name":"Jack Jill Smith-Jones","number":"+1 232324789"}]} {"user": "[email protected]","contact":[{"name":"X Æ A-12 Musk","number":"+1 23456789"},{"name":"Jack Jill","number":"+1 232324789"}]}
"name":"Jack "The big,ugly ripper" Johnson", "number":...Writing a regexp for that would be fairly hard. Btw, in your example, you need to have a double quote AFTER John:"name":"Jack "John""