我正在尝试使用TypeScript项目中的函数验证字符串,以确保它只包含某些字符。该函数以字符串和选项对象作为参数,选项指定允许哪些字符。
函数如下:
/**
* Validates a string to ensure it only contains allowed characters.
* @param {string} name - The string to validate.
* @param {Object} [options] - The options to use for validation.
* @param {boolean} [options.allowNumbers=false] - Whether to allow numbers.
* @param {boolean} [options.allowSpecialCharacters=false] - Whether to allow special characters.
* @param {boolean} [options.allowSpaces=false] - Whether to allow spaces.
* @param {boolean} [options.allowUnderscores=false] - Whether to allow underscores.
* @param {boolean} [options.allowDashes=false] - Whether to allow dashes.
* @param {boolean} [options.allowPunctuation=false] - Whether to allow punctuation.
* @param {boolean} [options.allowCyrillic=false] - Whether to allow Cyrillic characters.
* @param {boolean} [options.allowNonLatin=false] - Whether to allow non-Latin characters.
* @returns {boolean} Whether the string is valid or not.
*/
interface IValidateNameOptions {
allowNumbers?: boolean;
allowSpecialCharacters?: boolean;
allowSpaces?: boolean;
allowUnderscores?: boolean;
allowDashes?: boolean;
allowPunctuation?: boolean;
allowCyrillic?: boolean;
allowNonLatin?: boolean;
}
interface IValidateName {
(name: string, options?: IValidateNameOptions): boolean;
}
export const validateName: IValidateName = (
name,
options = {
allowNumbers: false,
allowSpecialCharacters: false,
allowSpaces: false,
allowUnderscores: false,
allowDashes: false,
allowPunctuation: false,
allowCyrillic: false,
allowNonLatin: false,
},
) => {
let regexStr = `^[a-zA-Z`;
if (options.allowNonLatin) {
regexStr += `\\p{L}`;
}
if (options.allowNumbers) {
regexStr += `0-9`;
}
if (options.allowSpecialCharacters) {
regexStr += `\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\_\\=\\+\\[\\]\\{\\}\\|\\\\\\;\\:\\'\\,\\.\\/\\<\\>\\?`;
}
if (options.allowSpaces) {
regexStr += `\\s`;
}
if (options.allowUnderscores) {
regexStr += `\\_`;
}
if (options.allowDashes) {
regexStr += `\\-`;
}
if (options.allowPunctuation) {
regexStr += `\\p{P}`;
}
if (options.allowCyrillic) {
regexStr += `\\p{Cyrillic}`;
}
regexStr += `]+$`;
const regex = new RegExp(regexStr, 'u');
return regex.test(name);
};
下面是jest测试:
it('should return true when name is valid and allowSpecialCharacters is true', () => {
expect(validateName('Deri!', { allowSpecialCharacters: true })).toBe(true);
});
这里是错误测试:
FAIL src/tests/validateName.test.ts
✓ should return true when name is valid (3 ms)
✓ should return false when name is invalid (6 ms)
✕ should return true when name is valid and allowSpecialCharacters is true (2 ms)
● should return true when name is valid and allowSpecialCharacters is true
SyntaxError: Invalid regular expression: /^[a-zA-Z\!\@\#\$\%\^\&\*\(\)\-\_\=\+\[\]\{\}\|\\\;\:\'\,\.\/\<\>\?]+$/: Invalid escape
at new RegExp (<anonymous>)
69 | regexStr += `]+$`;
70 |
> 71 | const regex = new RegExp(regexStr, 'u');
| ^
72 | return regex.test(name);
73 | };
74 |
at validateName (src/lib/validateName.ts:71:17)
at Object.<anonymous> (src/tests/validateName.test.ts:41:22)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 2 passed, 3 total
Snapshots: 0 total
Time: 1.536 s
Ran all test suites.
然而,当我尝试使用该函数时,我总是得到一个“无效转义”错误,即使我已经转义了所有的特殊字符。有人能告诉我我做错了什么吗?谢谢!
答案解释和正确的RegExp代码
3条答案
按热度按时间rsaldnfx1#
问题似乎出在
'u'
选项上。不知道它到底有什么变化(除了允许unicode转义),但它似乎对转义字符的处理有点不同。在
[]
中,除了少数例外,你不需要转义特殊字符。此外,要在Javascript中编写原始字符串,你可以使用`String.raw```。所以这应该行得通:
bkkx9g8r2#
如果你在浏览器中运行它,你会得到相同的结果
问题是你已经指定了- /u,这意味着它需要反斜杠字符,像这样在u前面
这是可行的:
wtlkbnrh3#
有些转义字符在JavaScript中不是特殊字符。当你使用Unicode模式和
u
标志时,你不能转义非特殊字符“以防万一”。这是禁止的,以确保将来添加特殊转义序列的可能性。比较:
所以你只需要转义
[ \ ^ $ . | ? * + ( )
,或者在[]
中更少。参见https://javascript.info/regexp-escaping和https://javascript.info/regexp-character-sets-and-ranges#escaping-in-。