Ubuntu 16 sed not working with parenthesis

Viewed 38

Oh, I can't get past this SED regex. This line "entrytimestamp" : ISODate("2020-09-09T16:07:34.526Z") in the first record should also be transformed but since it does not have a comma after the closing parenthesis it is not. Simply I want to remove "ISODate(" and the closing parenthesis ")". But it should not matter if is it the last element or not. I have double/triple checked the REGEX but I am missing something. Does anybody have any idea?

root@# cat inar.json
[
        {
                "_id" : ObjectId("5f58fdc632e4de001621c1ca"),
                "USER" : null,
                "entrytimestamp" : ISODate("2020-09-09T16:07:34.526Z")
        },
        {
                "_id" : ObjectId("5f590118c205630016dcafb4"),
                "entrytimestamp" : ISODate("2020-09-09T16:21:44.346Z"),
                "USER" : null
        }
]
sed -E "s/(.+\"entrytimestamp\"\s:\s)ISODate\((\"[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{1,3}Z\")\)(.+)/\1\2\3/" inar.json
[
        {
                "_id" : ObjectId("5f58fdc632e4de001621c1ca"),
                "USER" : null,
                "entrytimestamp" : ISODate("2020-09-09T16:07:34.526Z")
        },
        {
                "_id" : ObjectId("5f590118c205630016dcafb4"),
                "entrytimestamp" : "2020-09-09T16:21:44.346Z",
                "USER" : null
        }
]
2 Answers

You may use this sed:

sed -E 's/("entrytimestamp" *: *)ISODate\(([^)]+)\)/\1\2/' file
[
        {
                "_id" : ObjectId("5f58fdc632e4de001621c1ca"),
                "USER" : null,
                "entrytimestamp" : "2020-09-09T16:07:34.526Z"
        },
        {
                "_id" : ObjectId("5f590118c205630016dcafb4"),
                "entrytimestamp" : "2020-09-09T16:21:44.346Z",
                "USER" : null
        }
]

Command Details

  • ("entrytimestamp" *: *): Match starting "entrytimestamp" : part with optional spaces around :. Capture this part in group #1
  • ISODate\(: Match ISODate(
  • ([^)]+): Match 1+ of any character that is not ). Capture this part in group #2
  • \): Match closing )
  • /\1\2: Put back-references #1 and #2 back in substitution

Your regex does not match the first line you intend to match because of the last (.+) that matches at least one or more characters. As there is only a ) at the end and nothing else to match, the pattern fails.

Use (.*) to match any zero or more characters:

sed -E "s/(.+\"entrytimestamp\"\s:\s)ISODate\((\"[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{1,3}Z\")\)(.*)/\1\2\3/" inar.json

This is how the expression works.

Related