Регулярное выражение для сопоставления открывающей двойной кавычки с отсутствующей закрывающей двойной кавычкой

Регулярное выражение для сопоставления открывающей двойной кавычки с отсутствующей закрывающей двойной кавычкой

У меня есть большой (25 миллионов строк) файл данных, который |разделен каналом ( ). Поставщик данных предоставляет файлы, и я запускаю автоматизированные задания для загрузки файлов в базу данных Redshift, а затем обрабатываю данные.

Ниже приведен пример данных:

123|110092|ACCT|"HC Account"|"Account1||||||||||||"Mary"|||"|"||||132|"STE|504"|1253|Unspecified Account|||N||ACTV|Active||||04/30/2013|12/31/2099|||||||||||||

На данный момент я ознакомился с тремя наборами полевых данных:

  1. Текстовое поле заключено в двойные кавычки ( ") Например: "HC Account", "Mary", и "|". Это правильно, и данные должны быть загружены без кавычек.
  2. Некоторые значения будут содержать разделитель в виде вертикальной черты. Например: "STE|504". В этом случае поле обязательно должно быть заключено в двойные кавычки. Если это не так, оно попадает в третью категорию ниже.
  3. Иногда указывается только начальная цитата, а конечная отсутствует. Например: "Account1.

TL;DR: Любое поле, начинающееся с |", должно заканчиваться на "|. Если это не так и |"встречается другой, первую двойную кавычку необходимо экранировать.

Итак, после предварительной обработки в Unix/Python/других вариантах моя строка данных должна быть отредактирована и стать следующей:

123|110092|ACCT|"HC Account"|"Account1||||||||||||"Mary"|||"|"||||132|"STE|504"|1253|Unspecified Account|||N||ACTV|Active||||04/30/2013|12/31/2099|||||||||||||


Я планирую написать скрипт Unix для изменения файла с помощью SED. Регулярное выражение, которое я написал до сих пор, выглядит так:

(\|")(?!([a-zA-Z0-9]|\s|\||\/)*("\|))

Однако это не позволяет правильно сопоставить строку.

Вот ссылка, где я это тестирую:https://regexr.com/3toib

Я хочу, чтобы код был легким, поскольку средний размер файла составляет 3–5 ГБ, и таких файлов обычно несколько (более 10).

PS Redshift — это сервис баз данных AWS, использующий Postgre SQL Engine и способный удалять кавычки из правильно заключенных в кавычки полей и экранировать особое значение кавычек с помощью \.

Кроме того, я готов сделать это на Python/любом другом языке программирования, если код будет легким.

решение1

Есть одна ОГРОМНАЯ проблема с указанными вами спецификациями для данных. Если "|"является допустимой строкой, или, точнее, строка в кавычках может начинаться с вертикальной черты, то если строка с отсутствующей конечной кавычкой, например "Account1, имеет в качестве первого следующего поля в кавычках поле, которое начинается с вертикальной черты, например "|Mary", то нет способа определитьв любом случаеесли "|это конечная кавычка для |"Account1||||||||||||"|или начальная кавычка для |"|Mary"|.

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

123|110092|ACCT|"HC Account"|"Account1||||||||||||"|Mary|||"|||||132|"|STE|504|1253

можно увидеть, что это будет неправильно истолковано как

123 110092 ACCT "HC Account" "Account1||||||||||||" Mary   "|||||132|" STE 504 1253

Обратите внимание, что это проблема, независимо от того, используете ли вы регулярные выражения, Python или любой другой язык. Проблема общего случаяможетбыть «решена», но это будет сложно и потребует использования знаний о том, сколько полей существует в каждой строке, а также о структуре данных этих полей. (И всегда могут остаться неучтенные пограничные случаи.)


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

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

Это простейшее регулярное выражение, которое подойдет для большинства случаев:

                    Capturing Group 1           Capturing Group 2
               (All previous valid fields)  (Unclosed opening quote)
  __________________________|_________________________  |
 |                                                    || |
^((?:(?:(?!")[^|\r\n]*|"[^"\r\n]*"(?=$|\|))(?:$|\|))*+)(")
        |____________| |_________________| |______|
              |                 |              |
      Unquoted field  OR  Quoted field     EOL or hypen delimiter

Используйте его со следующей заменяющей строкой:

$1\\$2

Демо

Связанный контент