我正在尝试使用我的 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);
};
这里是笑话测试:
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代码
如果你在浏览器中运行它,你会得到相同的
const reg1 = /^[a-zA-Z\!\@\#\$\%\^\&\*\(\)\-\_\=\+\[\]\{\}\|\\\;\:\'\,\.\/\<\>\?]+$/u
console.log(reg1)
问题是你指定了 - /u 这意味着它期望反斜杠字符像这样以 u 开头
这有效:
// \u003a === :
const reg = /\u003a/u
const matched = ' :'.match(reg)
console.log(matched)
你的一些转义字符在 JavaScript 中不是特殊字符。当您使用带有
u
标志的 Unicode 模式时,您不能“以防万一”转义非特殊字符。这是禁止的,以确保将来添加特殊转义序列的可能性。
比较:
console.log(/:/); // No errors.
console.log(/\:/); // No errors as there is no u flag.
console.log(/\:/u); // Throws error.
所以你只需要逃离
[ \ ^ $ . | ? * + ( )
,或者更不用说在里面[]
.
参见https://javascript.info/regexp-escaping和https://javascript.info/regexp-character-sets-and-ranges#escaping-in-。