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

#regex #python-2.7

#регулярное выражение #python-2.7

Вопрос:

     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,
    • ИЗМЕНИТЬ ТАБЛИЦУ MD_CMPLY_PII_MASTER ДОБАВИТЬ СИМВОЛ SKIP_FLAG (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:

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

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

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

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

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

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

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

 import re
results = re.finditer(r"(s*[^sd](?:(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]
  

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

1. В приведенном выше регулярном выражении, как я могу избежать выбора следующей закрывающей скобки в следующем операторе? ALTER TABLE test ДОБАВИТЬ символ col1 (1 БАЙТ);

2. Смотрите дополнение к ответу.