Две последовательные заглавные буквы с конца - PullRequest
3 голосов
/ 06 октября 2019

Мне нужно регулярное выражение, которое поможет мне извлечь имя человека из строки, используя Stata.

Ниже приведены примеры строк:

name_adr
JAMES DeNORMANDIETrapelo Rd., Lincoln
JAMES A. KELLY, JR.Stafford St., Oxford
GEORGE WILLIAM SHATTUCKMt. Lebanon St., Pepperell

Ниже я нашел, что из них получилось:

name
JAMES DeNORMANDIE
JAMES A. KELLY, JR.
GEORGE WILLIAM SHATTUCK

Хитрость в том, что некоторые изимена имеют биты без заглавных букв.

Моя идея состояла в том, чтобы найти ту часть строки, где есть две последовательные заглавные буквы сзади. Простое регулярное выражение, которое я использовал, было [A-Z][A-Z][.*]$, но даже это не работает.

Есть идеи, как поступить?

Ответы [ 4 ]

5 голосов
/ 06 октября 2019

Взгляните на это регулярное выражение:

.+(?=(?:[A-Z]{2})|_)(?:(?:[A-Z])(?:[A-Z]\.)?)?

Regex Demo

Выход:

  • ДЖЕЙМС ДЕНОРМАНДИ
  • ДЖЕЙМС А. КЕЛЛИ, JR.
  • ДЖОРДЖ УИЛЬЯМ ШАТТУК

Объяснение:

.+                      # Match all characters
(?=[A-Z]{2}|_)          # Positive lookahead - assert that matches two capitals or _ (but does not capture)
(?:                     # Non-capturing group
  (?:[A-Z])             # Match one capital letter
  (?:[A-Z]\.)?          # Optionally match one capital letter followed by dot
)?                      # Non-capturing group is optional        

enter image description here

4 голосов
/ 06 октября 2019

Пример данных в виде кода Stata:

clear
input str49 name_adr
"JAMES DeNORMANDIETrapelo Rd., Lincoln"            
"JAMES A. KELLY, JR.Stafford St., Oxford"          
"GEORGE WILLIAM SHATTUCKMt. Lebanon St., Pepperell"
end

Это подход @ Emma:

local regex ^((?:[A-Z]+\s+){1,2}(?:[A-Z]\.\s*)*[A-Z][A-Za-z]*[A-Z])[A-Z][a-z]|^((?:[A-Z]+\s+){1,2}(?:[A-Z]\.\s*)*[A-Z][A-Za-z]*[A-Z]\s*,\s*JR.)

generate name = ustrregexs(1) + ustrregexs(2) if ustrregexm(name_adr, "`regex'")

     +-----------------------------------------------------------------------------+
     |                                          name_adr                      name |
     |-----------------------------------------------------------------------------|
  1. |             JAMES DeNORMANDIETrapelo Rd., Lincoln         JAMES DeNORMANDIE |
  2. |           JAMES A. KELLY, JR.Stafford St., Oxford       JAMES A. KELLY, JR. |
  3. | GEORGE WILLIAM SHATTUCKMt. Lebanon St., Pepperell   GEORGE WILLIAM SHATTUCK |
     +-----------------------------------------------------------------------------+

Это подход @ vs97:

local regex .+(?=(?:[A-Z]{2})|_)(?:(?:[A-Z])(?:[A-Z]\.)?)?

generate name = ustrregexs(0) if ustrregexm(name_adr, "`regex'")

list 
     +-----------------------------------------------------------------------------+
     |                                          name_adr                      name |
     |-----------------------------------------------------------------------------|
  1. |             JAMES DeNORMANDIETrapelo Rd., Lincoln         JAMES DeNORMANDIE |
  2. |           JAMES A. KELLY, JR.Stafford St., Oxford       JAMES A. KELLY, JR. |
  3. | GEORGE WILLIAM SHATTUCKMt. Lebanon St., Pepperell   GEORGE WILLIAM SHATTUCK |
     +-----------------------------------------------------------------------------+
1 голос
/ 07 октября 2019

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

gen name = strreverse(regexs(0)) if regexm(strreverse(name_adr), "([\.]*[A-Z][A-Z])(.*)")
replace name = substr(name, 1, strlen(name)-1) if substr(name, -3, .)!="JR."
1 голос
/ 06 октября 2019

Это довольно сложно, но, возможно, было бы неплохо попробовать несколько выражений в каждом конкретном случае и использовать чередование, например, с:

^((?:[A-Z]+\s+){1,2}(?:[A-Z]\.\s*)*[A-Z][A-Za-z]*[A-Z])[A-Z][a-z]|^((?:[A-Z]+\s+){1,2}(?:[A-Z]\.\s*)*[A-Z][A-Za-z]*[A-Z]\s*,\s*JR\.)

, и нужные выходные данные находятся взахват групп 1 и 2, как вы можете видеть в этом ответе .

Демо

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


Если вы хотите упростить / изменить / изучить выражение, это было объяснено на верхней правой панели regex101.com . При желании вы также можете посмотреть в эту ссылку , как она будет сопоставляться с некоторыми примерами входных данных.


RegEx Circuit

jex.im визуализирует регулярные выражения:

enter image description here

...