这是因为accented chars are stored differently on Mac OS X
and Windows.
Windows使用UTF-16作为文件名,因此大多数码点都进行了编码
在2个字节中.在基本多语言平面之外,它们被编码为
"代理项对",它将占用4个字节.这意味着您可以
我有一个像écosse.pdf
这样的文件,其中é
可以存储在一个
单码点或在两个码点中,其中将跟随e
由Unicode的尖锐口音´
.这意味着您的文件夹可以
将名为écosse.pdf
的文件存储两次(一次存储é
,一次存储
e
+´
),这可能非常令人困惑!
在Mac OS X上,他们使用UTF-8,但使用Unicode NFD
(N正规化F正则D分解).
这意味着é
将始终与2个码点一起存储:
e
+´
.这避免了多个文件具有相同的名称.
在JavaScript中,可以使用
.normalize()
种方法:
const filenames = [
'ecosse.pdf', // No accent at all
'écosse.pdf', // 1 codepoint to store "é"
'écosse.pdf' // 2 codepoints to store "é" = "e" + "´"
];
filenames.forEach(filename => {
// You can separate the letter and the accent codepoints with
// the help of .normalize('NFD');
const nfdFilename = filename.normalize('NFD');
console.log({
original: {
string: filename,
length: filename.length
},
NFD: {
string: nfdFilename,
length: nfdFilename.length
}
});
});
为了验证您的模式,您必须在以下两种模式之间进行 Select
NFD或NFC.此示例解释了您的问题:
const filenames = [
'różowo-żółty.pdf', // NFC (Most probably Windows)
'różowo-żółty.pdf', // NFD (Mac OS X)
'różowo-żółty.pdf', // mix of NFC and NFD (possible on Windows but not Mac OS X).
];
filenames.forEach(filename => {
const nfdFilename = filename.normalize('NFD');
const nfcFilename = filename.normalize('NFC');
console.log({
original: {
string: filename,
length: filename.length
},
NFD: {
string: nfdFilename,
length: nfdFilename.length
},
NFC: {
string: nfcFilename,
length: nfcFilename.length
}
});
});
顺便说一句,对于JavaScript,您可以使用u模式修饰符
或v模式修饰符,以启用Unicode处理.这将
为您提供使用\p{L}
来匹配任何
语言.对于\p{Latin}
,您可以更具体,但这可能
仍然不完全是你想要的,就像波兰人看起来的那样
另一个角色类.但if you convert the string
to NFC then you can use your pattern%:
const regexFilename = /^([\w\s()+[żźćńółęąśŻŹĆĄŚĘŁÓŃ-]+)(\.[A-Za-z0-9]+)?$/;
const filenames = [
'różowo-żółty.pdf', // NFC (Most probably Windows)
'różowo-żółty.pdf', // NFD (Mac OS X)
'różowo-żółty.pdf', // mix of NFC and NFD (possible on Windows but not Mac OS X).
];
filenames.forEach(filename => {
console.log({
filename: filename,
match: filename.normalize('NFC').match(regexFilename)
});
});