通过重新格式化现有文件名来重命名文件 - 与 -replace 运算符一起使用的替换字符串中的占位符

Posted

技术标签:

【中文标题】通过重新格式化现有文件名来重命名文件 - 与 -replace 运算符一起使用的替换字符串中的占位符【英文标题】:Renaming files by reformatting existing filenames - placeholders in replacement strings used with the -replace operator 【发布时间】:2017-04-02 15:12:03 【问题描述】:

我有一些这样的视频文件: 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处拆分字符串。 将字符串与中间的“_”连接起来。

【问题讨论】:

【参考方案1】:

-replace 使用的是regex,而不是wildcards。因此,您必须将替换更改为:

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

【讨论】:

【参考方案2】:

我强烈推荐 regex101.com 来学习正则表达式。

这样的东西可以工作:

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

给予:

VideoName_s01_e01.mp4

【讨论】:

【参考方案3】:

Martin Brandl's answer provides an elegant and effective solution,但值得深入挖掘:

PowerShell 的 -replace 运算符 (... -replace <search>[, <replace>]):

regular expression 作为其第一个操作数<search>(搜索表达式),并且总是全局匹配,即替换所有匹配。 p>

'bar' -replace '[ra]', '@' -> 'b@@'

指定替换表达式<replace>可选,在这种情况下空字符串 替换<search> 匹配的内容,从而使其有效删除

'bar' -replace '[ra]' -> 'b'

如果指定<replace>,则支持两种形式:

v6.1+(仅限 PowerShell Core):一个 脚本块 ( ... ) 作为替换操作数,它提供了完全在每个匹配的基础上动态计算替换字符串 - 有关示例,请参见 this answer。

'bar' -replace '[ra]', '' + $_.Value + '' -> 'bar'

一个 string 包含一个表达式,该表达式可以引用正则表达式捕获(和未捕获)的内容 - 例如 $& 来引用匹配的内容 - 下面将详细解释。

'bar' -replace '[ra]', '$&' -> 'bar'

-replace 匹配大小写-不敏感(也可以写成-ireplace);要执行区分大小写的匹配,请使用-creplace 形式。


在字符串类型的<replace> 操作数中引用正则表达式捕获的“替换语言”本身不是正则表达式 - 没有匹配发生,仅支持对正则表达式匹配的结果的引用,通过$-前缀占位符不要与混淆PowerShell 变量

PowerShell 的文档(现在)在其概念性about_Comparison_Operators 帮助主题中简要解释了替换字符串的语法。

完整图片参考Substitutions in Regular Expressions.NET框架帮助主题,因为PowerShell的-replace使用Regex.Replace()方法 在幕后。

为方便起见,以下是<replace> 字符串中支持的引用(摘自上面链接的页面,并添加了重点和注释):

$<em>number</em> (eg, $1) ... 包括替换字符串中由基于1<em>number</em> 标识的捕获组匹配的最后一个子字符串:

包括(...),一个带括号的子表达式,在正则表达式中隐式创建一个捕获组(捕获组)。默认情况下,此类捕获组未命名,并且必须由它们的 1-based(十进制)index 引用,反映它们在正则表达式中出现的顺序,所以$1 指的是你的正则表达式中的第一组捕获的内容,$2 指的是第二组捕获的内容,...

还支持用于数字消歧$<em>number</em>(例如$1)形式(例如,确保$1即使后面跟着@ 987654365@,使用$1000)。

您可以命名捕获组并按名称引用它们,而不是依赖 indices 来引用未命名的捕获组 - 请参阅下一点。

如果您对捕获组匹配的内容不感兴趣,您可以选择忽略它,通过 (?:...) 将其转换为非捕获组。

$<em>name</em> ... 包括替换字符串中由(?&lt;<em>name</em>&gt;...) 指定的命名捕获组匹配的最后一个子字符串。

$$ ... 在替换字符串中包含一个 "$" 文字

$&amp; ... 在替换字符串中包含整个匹配项的副本($0 也可以,尽管它是isn't directly documented)。

$` ... 在替换字符串中包含输入字符串匹配之前的文本。

$' ... 在替换字符串中包含输入字符串匹配后的文本。

$+ ... 在替换字符串中包含最后组捕获。 [这使您无需知道最后一组的具体索引。]

$_ ... 在替换字符串中包含整个输入字符串。

最后,请注意:

-replace 始终匹配全局,因此如果输入字符串包含多个匹配,则上述替换适用于每个 匹配。

通常最好对正则表达式和替换字符串使用'...'引号),因为单引号字符串是非扩展的(非-interpolating),因此避免与 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 &lt;search&gt;, $var.Replace('$', '$$') 这依赖于 [string]::Replace() method 执行文字子字符串替换。 附带说明一下,在简单情况下,此方法是 -replace 的替代方法,但请注意,默认情况下它是区分大小写的。 或者,使用 嵌套 -replace 操作,但由于转义要求,语法很棘手:... -replace &lt;search&gt;, ($var -replace '\$', '$$$$')

【讨论】:

【参考方案4】:

regex 是更好的解决方案,我建议使用其他格式化数字并使用模板

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

$template=@"
file*:prefix:Test1_sseason:01eepisode:01extension:.mp4
file*:prefix:1xxx_sseason:100eepisode:5extension:.mp4
file*:prefix:yyy3_sseason:10eepisode:02extension:.havi
"@



$exampleoffile | ConvertFrom-String -TemplateContent $template | 
%  "0_1:D2_e2:D23" -f $_.file.prefix, [int]$_.file.season, [int]$_.file.episode, $_.file.extension 

【讨论】:

以上是关于通过重新格式化现有文件名来重命名文件 - 与 -replace 运算符一起使用的替换字符串中的占位符的主要内容,如果未能解决你的问题,请参考以下文章

通过使用 nmake 文件附加系统时间来重命名 .exe 文件

如何通过在 Windows 中使用批处理替换子字符串来重命名文件 [关闭]

powershell 通过从文件名中删除“&”来重命名目录中的文件。

将当前时间分配给powershell变量

bash 通过添加数字批量重命名文件

使用 bash 脚本批量重命名 FTP 服务器上的文件