Переименование файлов путем переформатирования существующих имен файлов - заполнителей в строках замены, используемых с оператором -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??
Я просто не знаю, как сделать их переменными в разделе замены.
Я думаю, что лучший метод будет:
- Найти позицию
e??s??
(давайте назовем это X). - разбить строку в
X-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 }