Сопоставление регулярных выражений и увеличение имени файла (n)

#javascript #regex

#javascript #регулярное выражение

Вопрос:

Мне нужно написать регулярное выражение для использования в обеспечении отсутствия коллизии имен файлов.

Итак, я даю пользователю возможность сохранить как некоторое имя, а затем я сравниваю строку с массивом, и если возникает коллизия, я следую парадигме сохранения Windows.

Если вы сохраните test , это будет сохранено как test , если вы попытаетесь сохранить test снова, это станет test (1) . Теперь я хочу посмотреть, что (1) так

Условия

оно всегда будет начинаться с ( , а затем с N количеством символов 0-9 и заканчивается на ) .

Как я мог бы искать (1) or (169) с помощью регулярных выражений?
Я не уверен, что это минимальное количество символов, в котором я могу записать это регулярное выражение. Также в качестве дополнительного регулярного выражения, как бы я мог иметь то же самое, но также искать то же регулярное выражение, но с пробелом перед ( ?

Попытка:

То, что я придумал, const regEx = RegExp(/(?:()[0-9*](?:))/) однако это работает только для (1) , но не (11) и я не знаю, как также искать пробел перед (

Вероятно, это очень просто, но я не очень разбираюсь в регулярных выражениях.

Примеры строк, которые должны / не должны работать

 // Should work:
test (1)
test (594)
test (54)

// Shouldn't work
test (1
test 594)
test 54
  

Комментарии:

1. [0-9] , не [0-9*]

2. Обычно полезно, если вы включаете несколько примеров строк, которые должны совпадать, и строк, которые не должны совпадать.

3. @benvc верно, я должен был сделать это более явным и разделенным и привести больше примеров.

Ответ №1:

Строка должна заканчиваться на space(one or more digits)endOfString , чтобы вы могли:

 s((d ))$
  

дополнительные скобки (группа захвата) вокруг d предназначены для извлечения числа:

https://regex101.com/r/5OFix0/1

Сопоставление

 const sample = `test (0)
test (12)
test()
test(1)
test 1
ends with space (123) `;


sample.split('n').forEach(fileName => {

  const m = /s((d ))$/.exec(fileName);
	
  if (m amp;amp; m[1]) {       // if is incremented, AKA "fileName (n)"
    console.log(m[1]); // do your stuff here using m[1] string
  }

});  

Сопоставление и замена

Вот пример, в котором приведены примеры имен файлов (без расширений):

 /**
 * Detect " (n)" suffixed string. Return "n"
 * @param {String} name
 * @return {String|null} The integer string or null
 */
const isFilenameIncremented = name => {
  const m = /s((d ))$/.exec(name);
  return m amp;amp; m[1];
};

/**
 * Increment unsuffixed or " (n)" suffixed string
 * @dependency {Function} isFilenameIncremented
 * @param {String} name
 * @return {String} The " ((n|0) 1)" suffixed filename
 */
const incrementFilename = name => {
  const isInc = isFilenameIncremented(name);
  return isInc ? name.replace(/d (?=)$)/, m => ( m) 1) : `${name} (1)`;
}


const sample = `test (0)
test (12)
test()
test(1)
test 1
ends with space (123) `;

sample.split('n').forEach(filename => {
  const fileNameIncr = incrementFilename(filename);
  console.log( fileNameIncr )
});  

Которое должно увеличивать только два первых имени файла (от 0 до 1 и от 12 до 13) и добавлять (1) ко всем остальным, что приводит к следующему:

 test (1)  
test (13)  
test() (1)  
test(1) (1)  
test 1 (1)  
ends with space (123)  (1)  
  

Очевидно, что выше все еще не хватает проверки, существует ли это имя файла уже в массиве имен файлов, что может быть легко достигнуто с помощью fileNamesArray.includes(fileName)