使用Javascript正则表达式匹配重音字符

时间:2011-03-25 18:50:12

标签: javascript regex unicode internationalization

这是我今天遇到的一个有趣的片段:

/\ba/.test("a") --> true
/\bà/.test("à") --> false

然而,

/à/.test("à") --> true

首先, wtf?

其次,如果我想在单词的开头匹配重音字符,我该怎么做? (我真的想避免使用像/(?:^|\s|'|\(\) ....

这样的过顶选择器

6 个答案:

答案 0 :(得分:61)

这对我有用:

/^[a-z\u00E0-\u00FC]+$/i

here

的帮助下

答案 1 :(得分:40)

/\bà/.test("à")不匹配的原因是因为“à”不是单词字符。转义序列\b仅在单词字符边界和非单词字符之间匹配。 /\ba/.test("a")匹配,因为“a”是单词字符。因此,字符串的开头(不是单词字符)和字母“a”之间有一个边界。

JavaScript正则表达式中的单词字符定义为[a-zA-Z0-9_]

要匹配字符串开头的重音字符,只需使用正则表达式开头的^字符(例如/^à/)。该字符表示字符串的开头(与\b不同,它匹配字符串中的任何字边界)。它是最基本和标准的正则表达式,所以它绝对不会超过顶部。

答案 2 :(得分:2)

Stack Overflow在正则表达式中也存在非ASCII字符的问题,您可以找到它here。他们没有处理单词边界,但可能会给你提供有用的提示。

还有另一个page,但他希望匹配字符串,而不是单词。

我不知道,现在还没找到,是你问题的主播,但是当我看到我的第一个链接中使用了什么怪物正则表达时,你想要避免的群组不会超过顶部在我看来你的解决方案。

答案 3 :(得分:1)

如果您想匹配字母(无论是否带有重音),unicode property escapes可能会有所帮助。

/\p{Letter}*/u.test("à"); // true
/\p{Letter}/u.test('œ'); // true
/\p{Letter}/u.test('a'); // true
/\p{Letter}/u.test('3'); // false
/\p{Letter}/u.test('a'); // true

匹配单词的开头很棘手,但是(?<=(?:^|\s))似乎可以解决问题。 (?<= )是一个积极的回顾,确保在主表达式之前存在某些内容。 (?: )是一个非捕获组,因此在以后使用的任何匹配中,您最终都不会引用此部分。如果未设置多行标志,则^将匹配字符串的开头;如果已设置多行标志,则\s将匹配字符串的开头,并且/(?<=(?:^|\s))\p{Letter}*/u将匹配空格字符(空格/制表符/ linebreak)。

因此,将它们一起使用,将类似于:

/(?<=(?:^|\s))[^a-zA-Z]\p{Letter}*/u.match("bœ") // false /(?<=(?:^|\s))[^a-zA-Z]\p{Letter}*/u.match("œb") // true

如果只想 将重音符与字符串的开头匹配,则需要为a-zA-Z取反的字符集。

// Match characters, accented or not
let regex = /\p{Letter}+$/u;

console.log(regex.test("œb")); // true
console.log(regex.test("bœb")); // true
console.log(regex.test("àbby")); // true
console.log(regex.test("à3")); // false
console.log(regex.test("16 tons")); // true
console.log(regex.test("3 œ")); // true

console.log('-----');

// Match characters to start of line, only match characters

regex = /(?<=(?:^|\s))\p{Letter}+$/u;

console.log(regex.test("œb")); // true
console.log(regex.test("bœb")); // true
console.log(regex.test("àbby")); // true
console.log(regex.test("à3")); // false

console.log('----');

// Match accented character to start of word, only match characters

regex = /(?<=(?:^|\s))[^a-zA-Z]\p{Letter}+$/u;

console.log(regex.test("œb")); // true
console.log(regex.test("bœb")); // false
console.log(regex.test("àbby")); // true
console.log(regex.test("à3")); // false

SDL_WINDOW_SHOWN

答案 4 :(得分:0)

const regex = /^[\-/A-Za-z\u00C0-\u017F ]+$/;
const test1 = regex.test("à");
const test2 = regex.test("Martinez-Cortez");
const test3 = regex.test("Leonardo da vinci");
const test4 = regex.test("ï");

console.log('test1', test1);
console.log('test2', test2);
console.log('test3', test3);
console.log('test4', test4);

基于Wak和Cœur的答案:

/^[\-/A-Za-z\u00C0-\u017F ]+$/

也适用于空格和破折号。

例如:莱昂纳多·达·芬奇,马丁内斯·科尔特斯

答案 5 :(得分:0)

Unicode允许某些重音字符的两种替代但等效的表示形式。例如,é具有两个Unicode表示形式:'\u0039''\u0065\u0301'。前者称为合成形式,后者称为分解形式。 JavaScript允许在两者之间进行转换:

'é'.normalize('NFD') // decompose: '\u0039' -> '\u0065\u0301'
'é'.normalize('NFC') // compose: '\u0065\u0301' -> '\u0039'
'é'.length // composed form: -> 1
'é'.length // decomposed form: -> 2 (looks identical but has different representation)
'é' == 'é' // -> false (composed and decomposed strings are not equal)

代码点'\u0301'属于Unicode组合变音标记代码块0300-036F。因此,匹配这些重音字符的一种方法是将它们以分解形式进行比较:

// matching accented characters
/[a-zA-Z][\u0300-\u036f]+/.test('é'.normalize('NFD')) // -> true
/\bé/.test('é') // -> false
/\bé/.test('é'.normalize('NFD')) // -> true (NOTE: /\bé/ uses the decomposed form)

// matching accented words
/^\w+$/.test('résumé') // -> false
/^(?:[a-zA-Z][\u0300-\u036f]*)+$/.test('résumé'.normalize('NFD')) // -> true