Regex, как сопоставить некоторые заключительные паратезы, исключая другие в python - PullRequest
0 голосов
/ 08 апреля 2019
    CREATE TABLE "TEST_OWNER"."TEST_NOTIFY" 
    (   
    "test1" NUMBER,
    "test2" VARCHAR2 ( 200  BYTE ) ,  
    "test3" DATE,
    "test4" NUMBER,
    "test5" NUMBER(5, 6 ),
    "test6" TIMESTAMP (0 ) WITH TIME ZONE,
    "test7" VARCHAR2(200 BYTE ) 
    ) SEGMENT CREATION IMMEDIATE 
    PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
    NOCOMPRESS LOGGING
    STORAGE(INITIAL 4545 NEXT 56565 MINEXTENTS 1 MAXEXTENTS 898989
    PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
    BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
    TABLESPACE "TEST_TABLESPACE"
    ;
ALTER TABLE MD_CMPLY_PII_MASTER ADD SKIP_FLAG CHAR(1 BYTE);

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

  1. он не должен совпадать с закрывающей скобкой в ​​таких строках
    • "test2" VARCHAR2 ( 200 BYTE),
    • "test5" NUMBER(5, 6 ),
    • "test6" TIMESTAMP (0 ) WITH TIME ZONE,
    • ALTER TABLE MD_CMPLY_PII_MASTER ADD SKIP_FLAG CHAR (1 байт);

То есть, все закрывающие скобки, которые являются частью длины или точности, следует избегать при сопоставлении.

Из приведенного выше примера он должен соответствовать только закрывающим скобкам следующих строк:

  • ) SEGMENT CREATION IMMEDIATE
  • BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)

Я создал регулярные выражения, которые обнаруживают закрывающие скобки, которых следует избегать. Это:

  • для определения закрывающих скобок строки "test2" VARCHAR2 ( 200 BYTE ) ,:

    (?=\(\s{0,}\d+\s{0,}\w+\s{0,}(\)))
    

https://regex101.com/r/va73vG/1

  • для определения закрывающих скобок строки "test5" NUMBER(5, 6 ),:

     (?=\d+\s{0,}(\)))
    

https://regex101.com/r/zDbGUa/1

Я попытался объединить два приведенных выше регулярных выражения, но он по-прежнему соответствует всем закрывающим скобкам:

(?=(\)))(?!(\(\s{0,}\d+\s{0,}\w+\s{0,}\)))(?!(\d+\s{0,}\)))

https://regex101.com/r/Mtykby/1

Как получить желаемый результат?

обновлен

отвеченное регулярное выражение не работает для приведенного ниже оператора ALTER

ALTER TABLE test ADD SKIP_FLAG CHAR(1 BYTE);

Я обновил входные данные в вопросе. Какую модификацию я должен сделать, чтобы условия соответствовали новым входным данным?

ссылка: https://regex101.com/r/4Cu2wF/4

1 Ответ

1 голос
/ 08 апреля 2019

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

\)(?=(\([^()]*\)|[^()])*$)

$ должен обозначать конец ввода, а не конец строки, поэтому не используйте модификатор m.

Вышесказанное фактически находит закрывающие скобки, которые сами не содержатся во внешних скобках.

Альтернативный

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

Вот как это может работать в Python, учитывая строку str:

import re
results = re.finditer(r"\(\s*[^\s\d](?:\(\s*\d[^()]*\)|(?:(\))|.))*", str, re.DOTALL)
for match in results:
    pos = match.start(1) # position of the closing parenthesis
    print "pos = ", pos, ", near: ...", str[max(0,pos-10):pos+1]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...