从末尾开始连续两个大写字母

时间:2019-10-06 19:50:34

标签: regex stata

我想要一个正则表达式,可以帮助我使用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 个答案:

答案 0 :(得分:5)

看看这个正则表达式:

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

Regex Demo

输出:

  
      
  • JAMES DeNORMANDIE
  •   
  • JAMES A. KELLY,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

答案 1 :(得分:4)

数据示例为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 |
     +-----------------------------------------------------------------------------+

答案 2 :(得分:1)

这很复杂,但是也许可以视情况尝试多个表达式并使用替代方法,例如:

^((?:[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中,如您所见in this answer

Demo

这将使代码的编写变得简单,因为会出现新的情况,您将知道要更改或修改表达式的哪一部分。这只会使您的表情变长,但这没关系,特别是如果您想获得更好的准确性。


如果您希望简化/修改/探索表达式,请在regex101.com的右上角进行说明。如果愿意,您还可以在this link中查看它如何与某些示例输入匹配。


RegEx电路

jex.im可视化正则表达式:

enter image description here

答案 3 :(得分:1)

除了上述出色的答案外,我想出了另一种解决方案,该解决方案只是从背面查找两个连续的大写字母。万一这对其他人有帮助:

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."