我试图获取名称字符串的首字母,但该字符串可能包含一个我想忽略的标题,并且有多个或单个名称。如何仅使用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+$