Получение того, что осталось после удаления регулярного выражения - PullRequest
1 голос
/ 01 июля 2019

Контекст - это SQL в AS / 400 (IBM i)

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

Вот SQL:

select HAD1,                                                   
 regexp_substr(HAD1,'\b(GATE|LEVEL|DOOR|UNITS?)\s[\dA-Z]{1,}'),
 regexp_substr(HAD1,'**eventual_regex_goes_here**')                
from ECH                                                       
where regexp_like(HAD1,'\bGATE')                               

И желаемый результат:

Ship To                              REGEXP_SUBSTR     REGEXP_SUBSTR       
Address                                                                 
D2 COMPOUND, GATE 11                 GATE 11           D2 COMPOUND,  
2/22 GATEWAY DRIVE                   -                 2/22 GATEWAY DRIVE  
ASHBURTON FITTINGS  GATE 2           GATE 2            ASHBURTON FITTINGS
BRIERLY RD, GATE A, RIVER SIDE       GATE A            BRIERLY RD, , RIVER SIDE  
GATE 16, 37 KENEPURU DRIVE           GATE 16           , 37 KENEPURU DRIVE  

Если бы второе выражение тоже могло вывести запятые, это было бы здорово, но этоне требуется.Оставшаяся строка будет подвергнута другой (не-регулярной) обработке для удаления посторонних элементов (телефонных номеров, комментариев, знаков препинания и т. Д.)one , который дал следующую строку:

^.+?(?=\d{2})|(?<=\d{2}).+$

Итак, сначала я попытался поместить все свое выражение вместо обоих вхождений \d{2} и обнаружил, что это (неудивительно) не будет обрабатываться.Затем я вернулся к более простому тесту и попытался создать его оттуда.

Давайте попробуем просто слово GATE как константу плюс пару границ (потому что в глубине души я все еще ребенок,и вы знаете, что они говорят: «Детям нужны границы»).

select had1,                                                   
 regexp_substr(HAD1,'\b(GATE|LEVEL|DOOR|UNITS?)\s[\dA-Z]{1,}'),
 regexp_substr(HAD1,'^.+?(?=\bGATE\b)|(?<=\bGATE\b).+$')               
from ech                                                       
where regexp_like(HAD1,'\bGATE')      

Результат:

Ship To                                   REGEXP_SUBSTR     REGEXP_SUBSTR                 
Address                                                                                   
GATE 3, CNR QUARRY ROAD                   GATE 3             3, CNR QUARRY ROAD           
ASHBURTON FITTINGS  GATE 2                GATE 2            ASHBURTON FITTINGS            
GATE 6, HELLABYS ROAD                     GATE 6             6, HELLABYS ROAD             
GATE 3, 548 PAKAKARIKI HILL               GATE 3             3, 548 PAKAKARIKI HILL       
GATE 5 - FLIGHTYS COMPOUND                GATE 5             5 - FLIGHTYS COMPOUND        
GATE 3 - 548 PAEKAKARIKI HILL ROAD        GATE 3             3 - 548 PAEKAKARIKI HILL ROAD
GATE 14 - TAKAPU COMPOUND                 GATE 14            14 - TAKAPU COMPOUND         
35 GATEWAY DRIVE                          -                 -                             
GATE 6                                    GATE 6             6                            
TAKAPU ROAD,GATE 20,SH1                   GATE 20            TAKAPU ROAD,

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

Во втором и последнем ряду должно быть больше данных, '2' и ', SH1' соответственно.И строка «35 GATEWAY DRIVE» должна быть в последнем столбце.Я хочу все за исключением того, что находит выражение (которое на данный момент является целым словом GATE, запомните).

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

Ответы [ 3 ]

2 голосов
/ 01 июля 2019

Вы можете попробовать это:

with data (s) as (values
('D2 COMPOUND, GATE 11'), 
('2/22 GATEWAY DRIVE'),
('ASHBURTON FITTINGS  GATE 2'),
('BRIERLY RD, GATE A, RIVER SIDE'),
('GATE 16, 37 KENEPURU DRIVE')
) 
select s,
       regexp_substr(s,' ?(GATE|LEVEL|DOOR|UNITS) '),
       replace(regexp_replace(s,' ?(GATE|LEVEL|DOOR|UNITS) ',''),',',' ')
from   data

Результат:

D2 COMPOUND, GATE 11             GATE   D2 COMPOUND 11
2/22 GATEWAY DRIVE                 -    2/22 GATEWAY DRIVE
ASHBURTON FITTINGS  GATE 2       GATE   ASHBURTON FITTINGS 2
BRIERLY RD, GATE A, RIVER SIDE   GATE   BRIERLY RD A  RIVER SIDE
GATE 16, 37 KENEPURU DRIVE       GATE   16  37 KENEPURU DRIVE
1 голос
/ 01 июля 2019

Я знаю, что вы уже отметили правильный ответ, но вот один без всех этих replace с. Разница в том, что я выбрал пробелы и запятые по обе стороны от исходного REGEX, чтобы заменить их одним пробелом, а затем, если этот пробел приводит или завершает строку, я обрезаю его следующим образом:

CREATE TABLE strtest
  (string   varchar(255));

INSERT INTO strtest
VALUES ('D2 COMPOUND, GATE 11'),
       ('2/22 GATEWAY DRIVE'),
       ('ASHBURN FITTINGS  GATE 2'),
       ('BRIERLY RD, GATE A, RIVER SIDE'),
       ('GATE 16, 37 KENEPURU DRIVE')

select STRING,                                                   
       regexp_substr(STRING,'\b(GATE|LEVEL|DOOR|UNITS?)\s[\dA-Z]{1,}'),
       TRIM(regexp_REPLACE(STRING,'[ ,/-]*\b(GATE|LEVEL|DOOR|UNITS?)\s[\dA-Z]{1,}[ ,/-]*', ' '))
  from STRTEST                                                       
  where regexp_like(STRING,'\bGATE')
|STRING                                 |REGEXP_SUBSTR  |REGEX_REPLACE           |
|---------------------------------------|---------------|------------------------|
|D2 COMPOUND, GATE 11                   |GATE 11        |D2 COMPOUND             |
|2/22 GATEWAY DRIVE                     |               |2/22 GATEWAY DRIVE      |
|ASHBURN FITTINGS  GATE 2               |GATE 2         |ASHBURN FITTINGS        |
|BRIERLY RD, GATE A, RIVER SIDE         |GATE A         |BRIERLY RD RIVER SIDE   |
|GATE 16, 37 KENEPURU DRIVE             |GATE 16        |37 KENEPURU DRIVE       |
|LEVEL 3/27 NAPIER STREET               |LEVEL 3        |27 NAPIER STREET        |
|LEVEL 1 - MATT WILES                   |LEVEL 1        |MATT WILES              |

Магия заключается в выражениях [ ,]*, которые я прикрепил к началу и концу REGEXP. Если вы хотите получить тире и косую черту, просто сделайте это [ -,/]*.

У вас все еще есть эти проблемные записи DOOR TO и GATE AFTER, но они минимальны, и вы, вероятно, сможете исправить их позже.

0 голосов
/ 01 июля 2019

Я уже выбрал правильный ответ, любезно предоставленный user2398621.

Однако, для тех, кто играет дома, вот полный ответ почти готовый к применению в контексте данных, которые он будетбыть применены к.Комментарии заключаются в квадратные скобки, как / * this * /

select distinct HAD1 ,                                              
regexp_substr(HAD1 ,'\b(GATE|LEVEL|DOOR|UNITS?)\s[\dA-Z]{1,}'),     
trim(     /* remove leading/trailing blanks from REPLACE func */    
replace(   /* replace commas  */                                    
 replace(   /* replace slashes */                                   
  replace(   /* replace dashes  */                                  
   regexp_replace(HAD1 ,'\b(GATE|LEVEL|DOOR|UNITS?)\s[\dA-Z]{1,}',  
                  '')  /* replace extra address detail with null */ 
          ,'-',' ')                                                 
         ,'/',' ')                                                  
        ,',',' ')                                                   
     )                                                              
from ECH                                                            
where regexp_like(HAD1 ,'\b(GATE|LEVEL|DOOR|UNITS?)\b')             
  and length(trim(HAD1 )) > 12   /* show only longish addresses in sample */                                   

Образцы записей GATE

Ship To                                   REGEXP_SUBSTR    REGEXP_REPLACE    
Address                                                                       
GATE 6 52 MAHIA ROAD                      GATE 6           52 MAHIA ROAD        
ASHBURTON FITTINGS  GATE 2                GATE 2           ASHBURTON FITTINGS   
FIRST GATE AFTER THE ROUNDABOUT           GATE AFTER       FIRST  THE ROUNDABOUT
GATE 2,  61-63 NORMANBY ROAD              GATE 2           61 63 NORMANBY ROAD  
GATE 7, OFF MORRING STREET                GATE 7           OFF MORRING STREET   
GATE 7 OFF MORRIN STREET                  GATE 7           OFF MORRIN STREET    
GATE 6 SUBSTATION ROAD                    GATE 6           SUBSTATION ROAD      
VIA GATE 4, BUILDING 108                  GATE 4           VIA   BUILDING 108   

Образцы записей LEVEL (Обратите внимание, что пустая строка REGEXP_REPLACE в 1-й строке верна как для LEVEL, так и для UNIT (и ихномера) были удалены)

Ship To                                   REGEXP_SUBSTR    REGEXP_REPLACE
Address                                                          
LEVEL 2  UNIT 16                          LEVEL 2                                      
TRANSPOWER HOUSE - LEVEL 8                LEVEL 8          TRANSPOWER HOUSE             
LEVEL 3/27 NAPIER STREET                  LEVEL 3          27 NAPIER STREET             
LEVEL 2 GRAHAM STREET SERVICE CENTRE      LEVEL 2          GRAHAM STREET SERVICE CENTRE 
LEVEL 1 - MATT WILES                      LEVEL 1          MATT WILES                   
ANZ CENTRE, LEVEL 2                       LEVEL 2          ANZ CENTRE                   

Образцы записей DOOR

Ship To                                   REGEXP_SUBSTR   REGEXP_REPLACE
Address                                                               
NEXT DOOR TO 201                          DOOR TO         NEXT  201    
WAREHOUSE DOOR A                          DOOR A          WAREHOUSE    
DOOR 11 ( WAREHOUSE)                      DOOR 11         ( WAREHOUSE) 
DOOR 11 (WAREHOUSE)                       DOOR 11         (WAREHOUSE)  

Образцы записей UNIT

Ship To                                   REGEXP_SUBSTR   REGEXP_REPLACE
Address                                                               
UNIT B 11 LANGSTONE LANE                  UNIT B          11 LANGSTONE LANE   
26 BELFAST ROAD UNIT 1                    UNIT 1          26 BELFAST ROAD     
UNIT C 589 TERMAINE AVE                   UNIT C          589 TERMAINE AVE  
UNIT 1, 3 HENRY ROSE PLACE                UNIT 1          3 HENRY ROSE PLACE
UNIT 1/12 ANVIL ROAD                      UNIT 1          12 ANVIL ROAD     
UNIT D1, 269A MT SMART ROAD               UNIT D1         269A MT SMART ROAD

Вы заметите, что все еще есть несколько аномалий, дажев этом небольшом примере - например, иногда удаление текста, выделенного выражением, оставляет бессмысленный остаток, иногда нам нужна удаленная черта и т. д., но я возьму ручной пересмотр 5% по сравнению с ручным пересмотром 95% случаевэто требует внимания.

...