问题描述
我有一些这样的视频文件:VideoName_s01e01.mp4
,其中季节和情节是变量.我想在s??
和e??
之间添加下划线(_).
I have a few video file like this:VideoName_s01e01.mp4
where the season and episodes are variables. I want to add an underscore ("_") between the s??
and e??
.
我一直在使用 powershell 的问题进行重命名,我有一个起点:
I have been using powershell for renaming purposes, I have a starting point:
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
.
This actually renamed my files VideoName_s[0-9]_e[0-9].mp4
.
基本上,我正在寻找字符s??e??
,我只是不知道如何在替换部分中使它们成为变量.
Basically, I am looking for the characters s??e??
I just don't know how to make them variables in the replace section.
我认为最好的方法是:
- 找到
e??s??
的位置(我们称它为X). - 在
X-3
处分割字符串. - 将字符串与中间的"
_
"连接起来.
- Find the position of
e??s??
(let's call it X). - split the string at
X-3
. - concatenate the string with a "
_
" in the middle.
推荐答案
Martin Brandl的回答提供了一种优雅而有效的解决方案 ,但值得深入研究:
Martin Brandl's answer provides an elegant and effective solution, but it's worth digging deeper:
PowerShell的-replace
运算符(... -replace <search>[, <replace>]
):
PowerShell's -replace
operator (... -replace <search>[, <replace>]
):
-
采用 正则表达式 作为其第一个操作数
<search>
(搜索表达式),并且始终匹配 global ,即,它替换 all 匹配项
Takes a regular expression as its first operand,
<search>
(the search expression), and invariably matches globally, i.e., it replaces all matches.
-
'bar' -replace '[ra]', '@'
->'b@@'
'bar' -replace '[ra]', '@'
->'b@@'
指定替换表达式<replace>
是可选,在这种情况下,空字符串将替换为<search>
匹配的内容,从而导致有效的删除.
Specifying a replacement expression, <replace>
, is optional, in which case the empty string is substituted for what <search>
matched, resulting in its effective removal.
-
'bar' -replace '[ra]'
->'b'
'bar' -replace '[ra]'
->'b'
如果指定了<replace>
,则支持两种形式:
If <replace>
is specified, it supports two forms:
-
v6.1 + (仅适用于PowerShell Core ):一个 script块(
{ ... }
)作为替换操作数,可以在每次匹配的基础上完全动态地计算替换字符串-例如,请参见此答案.
v6.1+ (PowerShell Core only): A script block (
{ ... }
) as the replacement operand, which offers fully dynamic calculation of the replacement string on a per-match basis - see this answer for an example.
-
'bar' -replace '[ra]', { '{' + $_.Value + '}' }
->'b{a}{r}'
'bar' -replace '[ra]', { '{' + $_.Value + '}' }
->'b{a}{r}'
一个字符串,其中包含一个表达式,该表达式可以引用正则表达式捕获(和未捕获)的内容,
A string containing an expression that can reference what the regular expression captured (and didn't capture), explained below.
-
'bar' -replace '[ra]', '{$&}'
->'b{a}{r}'
'bar' -replace '[ra]', '{$&}'
->'b{a}{r}'
-replace
不区分大小写匹配- (也可以写为-ireplace
);要执行区分大小写的 匹配,请使用-creplace
形式.
-replace
matches case-insensitively (and can also be written as -ireplace
); to perform case-sensitive matching, use the form -creplace
.
替换语言"用于在字符串类型的<replace>
操作数中引用正则表达式捕获的对象本身不是正则表达式-此处不存在匹配项,仅引用结果 >支持的正则表达式匹配.
The "replacement language" for referencing regex captures in a string-typed <replace>
operand is itself not a regular expression - no matching happens there, only references to the results of the regex matching are supported.
值得注意的是,
-
PowerShell不会不在其
Get-Help about_comparison_operators
帮助主题,
PowerShell does not explain the syntax of replacement strings in its
Get-Help about_comparison_operators
help topic,
,但可以在正则表达式中的替换 .NET框架帮助主题,因为PowerShell的-replace
使用 Regex.Replace()
方法在幕后.
but the information can be found in the Substitutions in Regular Expressions .NET framework help topic, because PowerShell's -replace
uses the Regex.Replace()
methodbehind the scenes.
为方便起见,这是<replace>
字符串中受支持的引用(摘录自上面链接的页面,并添加了重点和注释):
For convenience, here are the references supported in the <replace>
string (excerpted from the page linked above, with emphasis and annotations added):
-
$number
(例如,$1
)...包括由基于1
的number
标识的捕获组匹配的最后一个子字符串,其中数字是替换字符串中的十进制值.
$number
(e.g.,$1
) ... Includes the last substring matched by the capture group that is identified by the1
-basednumber
, where number is a decimal value, in the replacement string.
- 注释:
-
在正则表达式中包含带括号的子表达式
(...)
会隐式创建一个捕获组(捕获组).默认情况下,此类捕获组为未命名,并且必须通过其基于1
的(十进制) index 进行引用,以反映它们在正则表达式中出现的顺序,以便$1
指的是正则表达式中第一个组所捕获的内容,$2
指的是第二个组中所捕获的内容,...
- Annotations:
Including
(...)
, a parenthesized subexpression, in the regex implicitly creates a capture group (capturing group). By default, such capture groups are unnamed and must be referenced by their1
-based (decimal) index reflecting the order in which they appear in the regex, so that$1
refers to what the 1st group in your regex captured,$2
to what the 2nd captured, ...
数字的消除歧义的格式
${number}
(例如,${1}
)也受支持(例如,即使后跟,也要确保识别出$1
,例如000
,请使用${1}000
).The form
${number}
(e.g.,${1}
) for disambiguation of the number is also supported (e.g., to make sure that$1
is recognized even if followed by, say,000
, use${1}000
).您可以命名命名捕获组并按名称引用它们,而不是依赖索引来引用它们-请参阅下一点.
Instead of relying on indices to refer to unnamed capture groups, you can name capture groups and refer to them by name - see next point.
如果您对捕获组匹配的内容不感兴趣,则可以选择忽略它,方法是使用
(?:...)
将其变成一个非捕获组.If you're not interested in what the capture group matched, you can opt to ignore it by turning it into a non-capturing group with
(?:...)
.${name}
... ...在替换字符串中包括由(?<name>...)
指定的命名组匹配的最后一个子字符串.${name}
... Includes the last substring matched by the named group that is designated by(?<name>...)
in the replacement string.$$
...在替换字符串中包含单个"$"
文字.$$
... Includes a single"$"
literal in the replacement string.$&
...在替换字符串中包含整个匹配项的副本($0
也可以,即使不是直接 已记录).$&
... Includes a copy of the entire match in the replacement string ($0
works too, even though it isn't directly documented).$`
... ...将替换字符串中输入字符串 之前的所有文本包括在内.$`
... Includes all the text of the input string before the match in the replacement string.$'
...在匹配字符串中包含输入字符串 之后的所有文本.$'
... Includes all the text of the input string after the match in the replacement string.$+
...在替换字符串中包括 最后个捕获的组. [这使您无需了解最后一组的特定索引.]$+
... Includes the last group captured in the replacement string. [This relieves you of the need to know the last group's specific index.]$_
...在替换字符串中包含整个 input 字符串.$_
... Includes the entire input string in the replacement string.最后,请注意:
-
-replace
始终匹配 global ,因此,如果输入字符串包含 multiple 个匹配项,则上述替换适用于 >每个匹配.
-replace
invariably matches globally, so if the input string contains multiple matches, the replacements above apply to each match.
对于正则表达式和替换字符串,通常最好使用
'...'
(单引号),因为单引号字符串不是扩展(非插值),因此避免与PowerShell自己的$
前缀标记的前期扩展和`
字符的解释混淆.如果确实需要包含PowerShell变量,则有三个选项:It is generally preferable to use
'...'
(single quotes) for both the regex and the replacement string, because single-quoted strings are non-expanding (non-interpolating), and therefore avoid confusion with PowerShell's own up-front expansions of$
-prefixed tokens and interpretation of`
chars.
If you do need to include a PowerShell variable, you have three options:使用
"..."
(扩展字符串)和`
-escape$
实例,这些实例用于 regex引擎;例如,在以下示例中为`$1
:'abc' -replace '(a)', "[`$1]-$HOME-"
,产生类似[a]-C:\Users\jdoe-bc
Use
"..."
(expanding strings) and`
-escape$
instances that are meant for the regex engine; e.g.,`$1
in the following example:'abc' -replace '(a)', "[`$1]-$HOME-"
, which yields something like[a]-C:\Users\jdoe-bc
使用字符串连接(
+
)从文字片段和变量引用构建字符串;例如:'abc' -replace '(a)', ('[$1]-' + $HOME + '-')
Build your string from literal pieces and variable references using string concatenation (
+
); e.g.:'abc' -replace '(a)', ('[$1]-' + $HOME + '-')
使用
-f
(字符串格式运算符字符串串联);例如:'abc' -replace '(a)', ('[$1]-{0}-' -f $HOME)
Use
-f
, the string-formatting operator string concatenation; e.g.:'abc' -replace '(a)', ('[$1]-{0}-' -f $HOME)
鉴于您需要使用
$$
在 replacement 字符串中转义文字$
,请使用以下惯用法来使用字面意义的变量:Given that you need to use
$$
to escape a literal$
in the replacement string, use the following idiom to use a variable whose value you want to use literally:-
... -replace <search>, $var.Replace('$', '$$')
- 这取决于
[string]::Replace()
方法 执行文字子字符串替换.
另外,在简单情况下,此方法是-replace
的替代方法,但请注意,默认情况下,此方法区分大小写 . - 或者,使用嵌套的
-replace
调用,但是由于转义的要求,语法很棘手:... -replace <search>, ($var -replace '\$', '$$$$')
... -replace <search>, $var.Replace('$', '$$')
- This relies on the
[string]::Replace()
method performing literal substring replacements.
On a side note, this method is an alternative to-replace
in simple cases, but note that it is case-sensitive by default. - Alternatively, use a nested
-replace
call, but the syntax is tricky due to the escaping requirements:... -replace <search>, ($var -replace '\$', '$$$$')
这篇关于通过重新格式化现有文件名来重命名文件-与-replace运算符一起使用的替换字符串中的占位符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
-