Переименование файлов путем переформатирования существующих имен файлов - заполнителей в строках замены, используемых с оператором -replace

У меня есть несколько видео файлов, как это:VideoName_s01e01.mp4 где сезон и эпизоды являются переменными. Я хочу добавить подчеркивание ("_") между s?? а также e??,

Я использовал PowerShell для переименования, у меня есть отправная точка:

GCI $path -filter '*_s??e??*' -rec |  Ren -new { $_.name -replace '_s[0-9][0-9]', '_s[0-9]_[0-9]_' } -passthru    

Это на самом деле переименовал мои файлы VideoName_s[0-9]_e[0-9].mp4,

В основном я ищу персонажей s??e?? Я просто не знаю, как сделать их переменными в разделе замены.

Я думаю, что лучший метод будет:

  1. Найти позицию e??s?? (давайте назовем это X).
  2. разбить строку в X-3,
  3. объединить строку с "_" в середине.

4 ответа

Решение

Ответ Мартина Брандла дает элегантное и эффективное решение, но стоит углубиться:

PowerShell-х -replace оператор (... -replace <search>, <replace>):

  • принимает регулярное выражение в качестве первого операнда, <search> (поисковое выражение), и неизменно совпадает глобально (находит все совпадения).

  • поддерживает ссылки на то, что регулярное выражение захватило (и не захватило) во 2-м операнде, <replace>, строка замещения (строка замещения).

"Язык замены" для ссылок на захваты регулярных выражений, поддерживаемые в <replace> само по себе не является регулярным выражением - совпадение не происходит, поддерживаются только ссылки на результаты сопоставления с регулярным выражением.

Следует отметить, что

  • PowerShell не объясняет синтаксис замещающих строк в своем Get-Help about_comparison_operators тема справки,

  • но информацию можно найти в разделе справки по подстановкам в регулярных выражениях.NET, потому что PowerShell -replace использует Regex.Replace() метод за кадром.

Для удобства, вот ссылки, поддерживаемые в <replace> (взято со страницы, ссылки на которую приведены выше, с акцентом и добавлением аннотаций):

  • $number (например, $1)... Включает последнюю подстроку, соответствующую группе захвата, которая идентифицируется как number, где number является десятичным значением в строке замены.

    • Аннотации:

      • Включая заключенное в скобки подвыражение (...) в вашем регулярном выражении неявно создает безымянную группу захвата (захвата). На неназванные группы ссылаются по индексу, начиная с 1, чтобы $1 относится к тому, что 1-я безымянная группа в вашем регулярном выражении захвачена, $2 к чему 2-й пленный,...
        Итак, какой первый ([0-9]{1,2}) в ответе Мартина, после s пойман, отражен в $1 и вторая неназванная группа, после e, в $2,

      • Форма ${number} (например, ${1}) для устранения неоднозначности номера также поддерживается (например, чтобы убедиться, что $1 распознается, даже если за ним, скажем, 000 использовать ${1}000).

  • ${name}... Включает последнюю подстроку, совпадающую с именованной группой, которая обозначена (?<name>...) в строке замены.

  • $$... Включает в себя один "$" литерал в строке замены.

  • $&... Включает копию всего соответствия в строке замены.

  • $`... Включает весь текст входной строки перед совпадением в строке замены.

  • $'... Включает весь текст входной строки после совпадения в строке замены.

  • $+... Включает последнюю группу, захваченную в строке замены. [Это освобождает вас от необходимости знать конкретный индекс последней группы.]

  • $_... Включает всю входную строку в строку замены.

Наконец, обратите внимание, что:

  • Обычно предпочтительнее использовать '...' как для регулярного выражения, так и для строки замещения. Т.е. используйте строки в одинарных кавычках, которые не расширяются (не интерполируются) и поэтому избегают путаницы с собственными предварительными расширениями PowerShell: $ с префиксами токенов.
    Если вам нужно включить переменную PowerShell, у вас есть два варианта:

    • использование "..." (расширяющиеся строки) и ` -побег $ экземпляры, предназначенные для движка регулярных выражений; например, `$1 в следующем примере:
      'abc' -replace '(a)', "[`$1]-$HOME-", который дает что-то вроде [a]-C:\Users\jdoe-bc
    • Создайте вашу строку из буквальных фрагментов и ссылок на переменные, используя конкатенацию строк (+); например:
      'abc' -replace '(a)', ('[$1]-' + $HOME + '-')
  • -replace Неизменно совпадает глобально, поэтому, если входная строка содержит несколько совпадений, приведенные выше замены применяются к каждому совпадению.

  • Учитывая, что вам нужно использовать $$ избежать буквального $ в строке замены используйте следующую идиому, чтобы использовать переменную, значение которой вы хотите использовать буквально:

    • ... -replace <search>, $var.Replace('$', '$$')
    • Это зависит от [string]::Replace() метод, выполняющий буквенные замены подстрок.
      С другой стороны, этот метод является альтернативой -replace в простых случаях, но обратите внимание, что он чувствителен к регистру по умолчанию.
    • В качестве альтернативы используйте вложенный -replace вызов, но синтаксис сложен из-за экранирования требований:
      ... -replace <search>, ($var -replace '\$', '$$$$')

Я настоятельно рекомендую regex101.com для изучения регулярных выражений.

Нечто подобное может работать:

"VideoName_s01e01.mp4" -replace '(.*s)(\d+)(e.*)', '$1$2_$3'

дает:

VideoName_s01_e01.mp4

-replace использует регулярные выражения, а не подстановочные знаки. Таким образом, вы должны изменить замену на:

-replace '_s([0-9]{1,2})e([0-9]{1,2})', '_s$1_e$2_'

regex - лучшее решение, я предлагаю другое с форматирующим номером и использую Template

$exampleoffile = @"
namev1_s01e01.mp4
namvev2_s03e02.mp4
VideoName_s20e15.mp4
VideoName_s15e1.mp4
VideoName_s1e16.avi
VideoName_s1e23.mv
"@

$template=@"
{file*:{prefix:Test1}_s{season:01}e{episode:01}{extension:.mp4}}
{file*:{prefix:1xxx}_s{season:100}e{episode:5}{extension:.mp4}}
{file*:{prefix:yyy3}_s{season:10}e{episode:02}{extension:.havi}}
"@



$exampleoffile | ConvertFrom-String -TemplateContent $template | 
% { "{0}_{1:D2}_e{2:D2}{3}" -f $_.file.prefix, [int]$_.file.season, [int]$_.file.episode, $_.file.extension }
Другие вопросы по тегам