提问人:IHaveSumQuestions 提问时间:11/19/2016 最后编辑:mklement0IHaveSumQuestions 更新时间:8/26/2023 访问量:3041
通过重新格式化现有文件名来重命名文件 - 与 -replace 运算符一起使用的替换字符串中的占位符
Renaming files by reformatting existing filenames - placeholders in replacement strings used with the -replace operator
问:
我有一些这样的视频文件:其中季节和剧集是变量。我想在 和 之间添加一个下划线 (“_”)。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??
我认为最好的方法是:
- 找到的位置(我们称之为 X)。
e??s??
- 在 处拆分字符串。
X-3
- 将字符串与中间的“”连接起来。
_
答:
-replace
使用的是正则表达式,而不是通配符。因此,您必须将替换更改为:
-replace '_s([0-9]{1,2})e([0-9]{1,2})', '_s$1_e$2_'
我强烈推荐 regex101.com 来学习正则表达式。
像这样的东西可以工作:
"VideoName_s01e01.mp4" -replace '(.*s)(\d+)(e.*)', '$1$2_$3'
给:
VideoName_s01_e01.mp4
Martin Brandl 的回答提供了一个优雅而有效的解决方案,但值得深入挖掘:
PowerShell 的 -replace
运算符 ():... -replace <search>[, <replace>]
将正则表达式作为其第一个操作数(搜索表达式),并且始终全局匹配,即替换所有匹配项。
<search>
'bar' -replace '[ra]', '@'
->'b@@'
- 如果要替换文本字符串,则必须单独对任何正则表达式元字符(例如)进行转义,或者使用
[regex]::Escape()
调用的结果:\
.
'bar.none' -replace '\.', '-'
->'bar-none'
'bar.none' -replace [regex]::Escape('.'), '-'
->'bar-none'
指定替换表达式 是可选的,在这种情况下,空字符串将替换为 whats,从而有效删除该表达式。
<replace>
<search>
'bar' -replace '[ra]'
->'b'
如果指定,则支持两种形式:
<replace>
v6.1+(仅限 PowerShell Core):脚本块 () 作为替换操作数,它基于每个匹配项提供替换字符串的完全动态计算:
{ ... }
'Level 41' -replace '\d+', { 1 + $_.Value }
->'Level 42'
一个字符串,其中包含一个表达式,该表达式可以引用正则表达式捕获(和未捕获)的内容 - 例如引用匹配的内容 - 下面将详细介绍。
$&
'bar' -replace '[ra]', '{$&}'
->'b{a}{r}'
-replace
不区分大小写地匹配(也可以写成 );要执行区分大小写的匹配,请使用 窗体 。-ireplace
-creplace
用于在字符串类型<replace>
操作数中引用正则表达式捕获的“替换语言”本身不是正则表达式 - 那里不会发生匹配,仅支持对正则表达式匹配结果的引用,通过 $
前缀的占位符,不要与 PowerShell 变量混淆。
PowerShell 的文档(现在)在其概念性
about_Comparison_Operators
帮助主题中简要介绍了替换字符串的语法。有关完整情况,请参阅正则表达式 .NET Framework 中的替换帮助主题,该主题适用,因为 PowerShell 使用
Regex.Replace()
方法 幕后花絮。-replace
为方便起见,以下是<replace>
字符串中支持的引用(摘自上面链接的页面,并添加了强调和注释):
$number
(例如,)......包括由替换字符串中
从1
开始的数字标识的捕获组匹配的最后一个子字符串:$1
包括括号内的子表达式,在正则表达式中隐式创建一个捕获组(capturing group)。默认情况下,此类捕获组是未命名的,并且必须由其基于
1
的(十进制)索引引用,以反映它们在正则表达式中的出现顺序,因此它指的是正则表达式中的第一个组捕获的内容,第二个捕获的内容,...(...)
$1
$2
还支持用于消除数字歧义的形式(例如,),以确保即使后面跟着 use 也能识别该形式(例如,)。
${number}
${1}
$1
000
${1}000
您可以命名捕获组并按名称引用它们,而不是依赖索引来引用未命名的捕获组 - 请参阅下一点。
如果您对捕获组匹配的内容不感兴趣,可以选择忽略它,方法是将其转换为带有 的非捕获组。
(?:...)
${name}
...包括与替换字符串中指定的命名捕获组匹配的最后一个子字符串。(?<name>...)
$$
...在替换字符串中包含单个“$”
文本。$&
...在替换字符串中包含整个匹配项的副本(也可以,即使它没有直接记录)。$0
$`
...在替换字符串中包括匹配项之前输入字符串的文本。$'
...在替换字符串中包括匹配项后的输入字符串的文本。$+
...包括替换字符串中捕获的最后一个组。[这样您就无需知道最后一组的特定索引。$_
...在替换字符串中包括整个输入字符串。
最后,请注意:
-replace
总是全局匹配,因此如果输入字符串包含多个匹配项,则上述替换项适用于每个匹配项。通常最好使用
“...”
(单引号)表示正则表达式和替换字符串,因为单引号字符串是非扩展的(非插值),因此避免与 PowerShell 自己的前缀标记的前期扩展和字符的解释混淆。
如果确实需要包含 PowerShell 变量或表达式,则有三个选项:$
`
使用用于正则表达式引擎的(可扩展字符串)和 -escape 实例;例如,在以下示例中:
它产生类似"..."
`
$
`$1
'abc' -replace '(a)', "[`$1]-$HOME-"
[a]-C:\Users\jdoe-bc
使用字符串连接从文本片段和变量引用构建字符串 ();例如:
+
'abc' -replace '(a)', ('[$1]-' + $HOME + '-')
使用 ,字符串格式运算符字符串连接;例如:
-f
'abc' -replace '(a)', ('[$1]-{0}-' -f $HOME)
假设您需要使用
$$
对替换字符串中的文本$
进行转义,请使用以下习惯用法来使用要按字面意思使用其值的变量:... -replace <search>, $var.Replace('$', '$$')
- 这依赖于执行文本子字符串替换的
[string]::Replace()
方法。
顺便说一句,此方法是简单情况下的替代方法,但请注意,默认情况下它区分大小写。-replace
- 或者,使用嵌套操作,但由于转义要求,语法很棘手:
-replace
... -replace <search>, ($var -replace '\$', '$$$$')
正则表达式是更好的解决方案,我建议其他格式化编号并使用模板
$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 }
评论