使用Regex从名称字符串中匹配首字母缩写,忽略标题



我试图获取名称字符串的首字母,但该字符串可能包含一个我想忽略的标题,并且有多个或单个名称。如何仅使用Javascript中的Regex才能做到这一点?

我可以将字符串中单词的第一个字符与b(w)匹配,但我想忽略"Mr"one_answers"Mrs"等。类似。。[^mr]b(w),但这会拾取mr中的M和前面的空白,并且不会忽略任何其他标题

字符串和匹配示例:

'Mr Bob Smith' -> BS
'Miss Jessica Blue' -> JB
'tim white' -> TW
'dr Lisa S pink' -> LS
'lord Lee Kensington-Smithe' -> LK

我可以使用负向前看和正向后看来解决这个问题。你可以试试这个:

function firstChars(str) {
	const regex = /(?!bmr.?b|bmissb|blordb|bdrb)((?<=s)|(?<=^))(b[a-z])/ig;
	const matches = [...str.match(regex)];
	
	return matches.map(char => char.toUpperCase()).join('');
}
console.log(firstChars('Mr Bob Smith'));
console.log(firstChars('Miss Jessica Blue'));
console.log(firstChars('tim white'));
console.log(firstChars('dr Lisa S pink'));
console.log(firstChars('Drone Picker'));
console.log(firstChars('lord Lee Kensington-Smithe'));
.as-console-wrapper{min-height: 100%!important; top: 0}

我更喜欢多步骤,而不是难以解析的正则表达式。

# Ignore case
name = "Mr. Frank Smith".lower()
# Get rid of the title 
name = re.sub("^(lord|mrs|mr)[.]? ","", name)
# get each first letter
name_list = name.split(" ")
for n in name_list:
# might need to exclude III, Jr. etc.
initials += n[0].upper()

从你的例子中,还不清楚你是想要中间名还是只想要前两个名字。根据您想要的内容,例如,您可以使用以下行而不是for循环:

# only first and second name, even if exclude last name
initials = name_list[0][0].upper() + name_list[1][0].upper()

如果LSP是可接受的,并且标题的大小写变体,则可以使用

let pattern = /b(?:(?:Mr|Miss|dr|lord)? )?(w+(?:[ -]w+)*)b/i;

Regex演示

let pattern = /b(?:(?:Mr|Miss|dr|lord)? )?(w+(?:[ -]w+)*)b/i;
let strings = [
"Mr Bob Smith",
"Miss Jessica Blue",
"tim white",
"dr Lisa S pink",
"lord Lee Kensington-Smithe"
];
strings.forEach(s => {
let m = s.match(pattern);
if (m) {
console.log(m[1].split(" ").map(s => s.charAt(0).toUpperCase()).join(""));
}
});

如果你只想匹配小写或大写的名字,你可以使用一个替换。对于标题,您也可以使用可选的替换。

b(?:(?:Mr|Miss|dr|lord)? )?((?:[A-Z]w*(?:[ -][A-Z]w*)*|[a-z]+(?: [a-z]+)))b

部件内

  • b字边界
  • (?:非捕获组
    • (?:Mr|Miss|dr|lord)?匹配任何备选方案
  • )?关闭组并使其可选
  • (捕获组1
    • (?:非捕获组
      • [A-Z]w*(?:[ -][A-Z]w*)*匹配以大写字母开头的部分
      • |
      • [a-z]+(?: [a-z]+)只匹配小写部分
    • )关闭组
  • )关闭组
  • b字边界

Regex演示

let pattern = /b(?:(?:Mr|Miss|dr|lord)? )?((?:[A-Z]w*(?:[ -][A-Z]w*)*|[a-z]+(?: [a-z]+)))b/;
let strings = [
"Mr Bob Smith",
"Miss Jessica Blue",
"tim white",
"dr Lisa S pink",
"lord Lee Kensington-Smithe"
];
strings.forEach(s => {
let m = s.match(pattern);
if (m) {
console.log(m[1].split(" ").map(s => s.charAt(0).toUpperCase()).join(""));
}
});

这里有更多面向javascript的方法:

var initials = fullNames.map(fullname => {
return fullname
.replace(/^(?:Mr|Miss|dr|lord).? ?/, '') // remove title
.split(' ')
.map(substring => substring[0].toUpperCase())
.join('')
.substring(0, 2) // this part is to match only 2 chars
});
// => [ 'BS', 'JB', 'TW', 'LS', 'LK' ]

如果您对'dr Lisa S pink' === LSP满意,您可以移除.substring(0, 2)零件

const fullNames = [
"Mr Bob Smith",
"Miss Jessica Blue",
"tim white",
"dr Lisa S pink",
"lord Lee Kensington-Smithe"
]
const initials = fullNames.map(fullname => {
return fullname
.replace(/^(?:Mr|Miss|dr|lord).? ?/, '')
.split(' ')
.map(substring => substring[0].toUpperCase())
.join('')
.substring(0, 2)
})
const initialsV2 = fullNames.map(fullname => {
return fullname
.replace(/^(?:Mr|Miss|dr|lord).? ?/, '')
.split(' ')
.map(substring => substring[0].toUpperCase())
.join('')
})
$('#initials').html(fullNames.map( (fullName, i) => `${fullName.padEnd(28, ' ')} => ${initials[i]}` ).join('n'))
$('#initials2').html(fullNames.map( (fullName, i) => `${fullName.padEnd(28, ' ')} => ${initialsV2[i]}` ).join('n'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<pre>
<h2>V1 only 2 letters</h2>
<div id='initials'></div>
<h2>V2 any letters length</h2>
<div id='initials2'></div>
</pre>

这适用于我的

(w)w+ (w)w+$

最新更新