Ubuntu 16 sed не работает со скобками

#regex #ubuntu #sed

#регулярное выражение #ubuntu #sed

Вопрос:

О, я не могу пройти мимо этого регулярного выражения SED. Эта строка «entrytimestamp» : ISODate(«2020-09-09T16:07:34.526Z») в первой записи также должна быть преобразована, но поскольку в ней нет запятой после закрывающей скобки, это не так. Просто я хочу удалить «ISODate (« и закрывающую скобку «)». Но не должно иметь значения, является ли это последним элементом или нет. Я дважды / трижды проверил регулярное выражение, но я чего-то не хватает. У кого-нибудь есть идеи?

 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"))(. )/123/" 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
        }
]
  

Ответ №1:

Вы можете использовать это sed :

 sed -E 's/("entrytimestamp" *: *)ISODate(([^)] ))/12/' 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
        }
]
  

Подробности команды

  • ("entrytimestamp" *: *) : Сопоставьте начальную "entrytimestamp" : часть с необязательными пробелами вокруг : . Запишите эту часть в группу # 1
  • ISODate( : Совпадение ISODate(
  • ([^)] ) : Сопоставьте 1 любого символа, который не является ) . Запишите эту часть в группу # 2
  • ) : Закрытие соответствия )
  • /12 : Верните обратные ссылки # 1 и # 2 обратно в замену

Комментарии:

1. это определенно работает, спасибо. Я просто не понимаю, почему мое регулярное выражение этого не сделало. Если кто-нибудь знает, почему, пожалуйста, покажите мне свет.

2. Используя ваше регулярное выражение, вы можете попробовать: sed -E 's/(.*"entrytimestamp" *: *)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"))(.*)/123/' file

3. Хорошо, я вижу, что это связано с жадностью знака плюс по сравнению со знаком звезды. Я читаю на сайте gnu sed, но действительно вижу «почему». Но спасибо, что указали мне направление.

Ответ №2:

Ваше регулярное выражение не соответствует первой строке, которую вы собираетесь сопоставить, из-за последней, (. ) которая соответствует по крайней мере одному или нескольким символам. Поскольку в конце есть только ) и больше ничего подходящего, шаблон не выполняется.

Используйте (.*) для сопоставления любого нуля или более символов:

 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"))(.*)/123/" inar.json
  

Вот как работает выражение.