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

我有一些这样的视频文件: VideoName_s01e01.mp4 季节和剧集是可变的。我想在s??e?? 之间添加一个下划线(“_”)。

我一直使用 进行重命名,我有一个起点:

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. 将字符串与中间的“_”连接起来。

【问题讨论】:

    标签: powershell file powershell replace rename


    【解决方案1】:

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

    -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 + '}' } -> 'b{a}{r}'
          • 一个 string 包含一个表达式,该表达式可以引用正则表达式捕获(和未捕获)的内容 - 例如 $& 来引用匹配的内容 - 下面将详细解释。

            • 'bar' -replace '[ra]', '{$&}' -> 'b{a}{r}'
        • -replace 匹配大小写-不敏感(也可以写成-ireplace);要执行区分大小写的匹配,请使用-creplace 形式。


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

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

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

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

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

          • 您可以命名捕获组并按名称引用它们,而不是依赖 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}_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 }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-10-07
            • 2021-02-12
            • 2016-08-06
            • 1970-01-01
            • 2018-04-10
            • 2017-10-11
            相关资源
            最近更新 更多