我想要一个正则表达式,可以帮助我使用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][.*]$
,但即使这样也不起作用。
任何想法如何进行?
答案 0 :(得分:5)
看看这个正则表达式:
.+(?=(?:[A-Z]{2})|_)(?:(?:[A-Z])(?:[A-Z]\.)?)?
输出:
- 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
答案 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。
这将使代码的编写变得简单,因为会出现新的情况,您将知道要更改或修改表达式的哪一部分。这只会使您的表情变长,但这没关系,特别是如果您想获得更好的准确性。
如果您希望简化/修改/探索表达式,请在regex101.com的右上角进行说明。如果愿意,您还可以在this link中查看它如何与某些示例输入匹配。
jex.im可视化正则表达式:
答案 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."