Vi: Файл SQL с шаблоном подстановки. Проблема с регулярным выражением

#regex #vi #substitution

Вопрос:

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

Например, у нас есть :

         (1,2956,2026442,4,NULL,NULL,'ZAC DU BOIS DES COMMUNES','',NULL,NULL,'Rue DU LUXEMBOURG',NULL,
    '9999','EVREUX',NULL,1,'27229',NULL,NULL,NULL,NULL,NULL,' Rue DU LUXEMBOURG, 9999 EVREUX',NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'2020-07-08 16:34:40',NULL,NULL)
 

Итак, у нас 40 колонок, и я оставляю 13. Мое регулярное выражение таково :

     (1),2,(3),4-5,(6-14),15-22,(23),24-39,(40)
:%s/((.{-}),.{-},(.{-}),.{-},.{-},(.{-},.{-},.{-},.{-},.{-},.{-},.{-},.{-},.{-}),.{-},
    .{-}, .{-},.{-},.{-},.{-},.{-},.{-},(.{-}),.{-},.{-},.{-},.{-},.{-},.{-},.{-},.{-},.{-},.{-},.{-},
    .{-},.{-},.{-},.{-},.{-},(.{-}))/(1,2,3,4,5)/g
 

Я заключаю в скобки части, которые меня интересуют, заключая их в скобки (я получаю только значения в скобках в строке над моим регулярным выражением ). Затем с помощью замены я восстанавливаю эти группы.

Так что обычно мой результат должен быть :

 (1,2026442,NULL,'ZAC DU BOIS DES COMMUNES','',NULL,NULL,'Rue DU LUXEMBOURG',NULL,
        '9999','EVREUX',' Rue DU LUXEMBOURG, 9999 EVREUX',NULL)
 

Но потому что внутри ' Rue DU LUXEMBOURG, 9999 EVREUX' есть запятая (,). Моим результатом станет :
(1,2026442,NULL,'ZAC DU BOIS DES COMMUNES','',NULL,NULL,'Rue DU LUXEMBOURG',NULL,'9999','EVREUX',' Rue DU LUXEMBOURG',NULL,NULL)

Может ли мне помочь кто-нибудь, кто хорошо разбирается в регулярных выражениях ? заранее спасибо. Если я не был ясен, скажите мне тоже, я постараюсь объяснить лучше в следующий раз.

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

1. Каково здесь правило? Как вы можете описать контекст, в котором запятая должна быть «пропущена»? Могут ли другие поля содержать «дикие» запятые?

2. в этом конкретном случае нам нужно, чтобы запятая оставалась, потому что она принадлежит столбцу varchar. На самом деле, дикая запятая появляется только в строке.

Ответ №1:

Я предлагаю сопоставить поля, которые могут быть строками, с %('[^']*'|w*) шаблоном, то есть группой без захвата, которая находит либо ' ноль или более не- ' s, а затем ' символ, либо любой ноль или более буквенно-цифровых символов.

Кроме того, использование групп без захвата (в Vim это %(...) в very magic режиме или %(...) в обычном режиме) и very magic режиме может помочь сократить шаблон.

Весь узор будет выглядеть так

 :%s/v(([^,]*),[^,]*,([^,]*),[^,]*,[^,]*,(%('[^']*'|w*)%(,%('[^']*'|w*)){8})%(,%('[^']*'|w*)){8},('[^']*'|w*)%(,%('[^']*'|w*)){16},([^,]*))/(1,2,3,4,5)/g
 

Смотрите демонстрационную версию регулярного выражения, преобразованную в регулярное выражение PCRE.

Обратите внимание, что некоторые поля, которые не являются строками [^,]* , сопоставляются с нулем или более символов, отличных от запятой. %(,%('[^']*'|w*)){8} Подобные шаблоны соответствуют (здесь) 8 вхождениям последовательности , символов '...' подстрока или нулю или более символов слов.