Справочная информация
Я работаю над обработкой списка имен пользователей, разделенных запятыми (для оптимизации белого списка ACL в моем проекте), и мне нужно нормализовать пробелы вокруг запятых, а также обрезать начальные и конечные пробелы в строке.
Код и проблема
Я использовал эту замену регулярного выражения для очистки строки:
const input = "a,b,c ";
const result = input.replace(/\s*,\s*|^\s*|\s*$/g, ',');
console.log(result); // Outputs "a,b,c,," (two trailing commas)
"a,b,c ".replace(/\s*,\s*|^\s*|\s*$/g, ',') // outputs two tailing commas
"c ".replace(/(\s*$)/g, ','); // outputs two tailing commas
function checkByIndexOf(commaStr, target) {
const wrappedStr = `,${commaStr},`;
const wrappedTarget = `,${target},`;
return wrappedStr.indexOf(wrappedTarget) !== -1;
}
/**
* High-performance check: indexOf + boundary validation (supports spaces/dots/no special chars)
* @param {string} commaStr - Comma-separated string (may contain spaces, dots)
* @param {string} target - Target item (may contain dots)
* @returns {boolean} Whether the target is included as a standalone item
*/
function checkByIndexOfWithBoundary(commaStr, target) {
const targetLen = target.length;
const strLen = commaStr.length;
let pos = commaStr.indexOf(target);
// Return false immediately if target is not found
if (pos === -1) return false;
// Loop through all matching positions (avoid missing matches, e.g., duplicate items)
while (pos !== -1) {
// Check front boundary: start of string / previous char is comma/space
const prevOk = pos === 0 || /[, ]/.test(commaStr[pos - 1]);
// Check rear boundary: end of string / next char is comma/space
const nextOk = (pos + targetLen) === strLen || /[, ]/.test(commaStr[pos + targetLen]);
// Return true if both boundaries match (target is a standalone item)
if (prevOk && nextOk) return true;
// Find next matching position (avoid re-matching the same position)
pos = commaStr.indexOf(target, pos + 1);
}
// All matching positions fail boundary validation
return false;
}
/**
* Check if a comma-separated string contains a specified standalone item
* @param {string} commaStr - Original comma-separated string (e.g. "apple,banana,orange")
* @param {string} target - Target string to check (e.g. "banana")
* @returns {boolean} Whether the target item is included as a standalone entry
*/
function checkCommaStrInclude(commaStr, target) {
// Escape regex special characters in the target string (e.g. . * + ? $ ^ [ ] ( ) { } | \ /)
const escapedTarget = target.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// Build regex pattern: match (start of string | comma) + escaped target + (comma | end of string)
// Ensures the target is a standalone item (avoids partial matches)
const regex = new RegExp(`(^|,)${escapedTarget}(,|$)`, 'g');
// Test if the regex matches the comma-separated string
return regex.test(commaStr);
}
Проблема
Ожидаемый результат — «a,b,c» (без завершающих запятых, нормализованные запятые), но вместо этого текущий код выдает две завершающие запятые. Я не понимаю, почему регулярное выражение совпадает таким образом, что в конце добавляются дополнительные запятые.
Что я пробовал
Я проверил шаблон регулярного выражения /\s*,\s*|^\s*|\s*$/g и понял, что оно должно соответствовать:
[*]Я заменил все совпадения на ,, но завершающий пробел во входных данных, кажется, вызывает две замены, которые приводят к двойным запятым.
Вопрос
Почему это регулярное выражение создает две конечные запятые для входных данных "a,b,c" "?
Как я могу настроить регулярное выражение (или использовать лучший подход), чтобы получить чистый вывод "a,b,c" для строк, разделенных запятыми, с дополнительными пробелами/запятыми?
Справочная информация Я работаю над обработкой списка имен пользователей, разделенных запятыми (для оптимизации белого списка ACL в моем проекте), и мне нужно нормализовать пробелы вокруг запятых, а также обрезать начальные и конечные пробелы в строке. Код и проблема Я использовал эту замену регулярного выражения для очистки строки:
/** * High-performance check: indexOf + boundary validation (supports spaces/dots/no special chars) * @param {string} commaStr - Comma-separated string (may contain spaces, dots) * @param {string} target - Target item (may contain dots) * @returns {boolean} Whether the target is included as a standalone item */ function checkByIndexOfWithBoundary(commaStr, target) { const targetLen = target.length; const strLen = commaStr.length; let pos = commaStr.indexOf(target);
// Return false immediately if target is not found if (pos === -1) return false;
// Loop through all matching positions (avoid missing matches, e.g., duplicate items) while (pos !== -1) { // Check front boundary: start of string / previous char is comma/space const prevOk = pos === 0 || /[, ]/.test(commaStr[pos - 1]); // Check rear boundary: end of string / next char is comma/space const nextOk = (pos + targetLen) === strLen || /[, ]/.test(commaStr[pos + targetLen]);
// Return true if both boundaries match (target is a standalone item) if (prevOk && nextOk) return true;
// Find next matching position (avoid re-matching the same position) pos = commaStr.indexOf(target, pos + 1); }
// All matching positions fail boundary validation return false; }
/** * Check if a comma-separated string contains a specified standalone item * @param {string} commaStr - Original comma-separated string (e.g. "apple,banana,orange") * @param {string} target - Target string to check (e.g. "banana") * @returns {boolean} Whether the target item is included as a standalone entry */ function checkCommaStrInclude(commaStr, target) { // Escape regex special characters in the target string (e.g. . * + ? $ ^ [ ] ( ) { } | \ /) const escapedTarget = target.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// Build regex pattern: match (start of string | comma) + escaped target + (comma | end of string) // Ensures the target is a standalone item (avoids partial matches) const regex = new RegExp(`(^|,)${escapedTarget}(,|$)`, 'g');
// Test if the regex matches the comma-separated string return regex.test(commaStr); }[/code]
Проблема Ожидаемый результат — «a,b,c» (без завершающих запятых, нормализованные запятые), но вместо этого текущий код выдает две завершающие запятые. Я не понимаю, почему регулярное выражение совпадает таким образом, что в конце добавляются дополнительные запятые. Что я пробовал [list] [*]Я проверил шаблон регулярного выражения /\s*,\s*|^\s*|\s*$/g и понял, что оно должно соответствовать:
[*]Я заменил все совпадения на ,, но завершающий пробел во входных данных, кажется, вызывает две замены, которые приводят к двойным запятым.
Вопрос [list] [*]Почему это регулярное выражение создает две конечные запятые для входных данных "a,b,c" "? [*]Как я могу настроить регулярное выражение (или использовать лучший подход), чтобы получить чистый вывод "a,b,c" для строк, разделенных запятыми, с дополнительными пробелами/запятыми? [/list]