【问题标题】:Replacing 2nd occurrence of "-" with "_" using Powershell使用 Powershell 将第二次出现的“-”替换为“_”
【发布时间】:2019-04-19 02:34:12
【问题描述】:

我一直在使用 Powershell 来简化创建目录、重命名和移动文件的重复性任务。我正在处理文件名所需的语法非常具体的视频和 PDF 文件。到目前为止,我已经能够纠正我遇到的所有常见错误,但是这个让我很难过。

我的文件的正确语法包括:

01A-50_02A-50-CIPP-PRE.MP4
01AA-50_02AA-50-CIPP-PNSL.PDF
W01AA-48_02AA-48-CIPP-PST-CMP.MPG

我收到了大量如下所示的文件:

01A-50-02A-50-CIPP-PRE.MP4
01AA-50-02AA-50-CIPP-PNSL.PDF
W01AA-48-02AA-48-CIPP-PST-CMP.MPG

我需要用下划线替换第二个破折号,同时保持其他破折号不受影响。否则,我可以在 excel 的帮助下批量执行此操作,但我希望有一个简短的代码,可以在语法中找到并纠正此错误,而无需将列表导出到 excel,使用文本到列,然后连接字母数字部分重新组合在一起。我也不想手动更正所有这些文件名。

根据我的研究,不可能针对特定出现的字符进行替换。我最接近的想法是我找到了一个涉及 REGEX 以及识别和替换模式的解决方案。我无法对此做任何建设性的事情。

我使用此代码的方法是打开包含错误命名文件的文件夹,在其中打开一个 Powershell 窗口,从我桌面上的 txt 文件中复制代码,然后将其粘贴到 Powershell 中。

对此的任何帮助将不胜感激。

【问题讨论】:

    标签: regex powershell replace renaming


    【解决方案1】:

    -replace 运算符与正则表达式一起使用:

    Get-ChildItem |
      Rename-Item -NewName { $_.Name -replace '^([^_-]+-[^_-]+)-', '$1_' } -WhatIf
    

    -WhatIf预览重命名操作;删除它以执行实际重命名。

    • Regex '^([^_-]+-[^_-]+)-' 捕获文件名开头 (^) 的前两个 - 分隔标记,使用捕获组 ((...)) 捕获除第二个 - 之外的标记。

      • [^_-]+ 捕获既不是- 也不是_ 的任何非空字符运行。 _ 也被排除在外,以防止误报已经正确正确的文件名;对于那些,不排除 _ 将匹配第一个 3 标记并在那里插入 additional _
    • 替换操作数 $1_ 然后使用第一个(也是唯一的)捕获组 ($1) 的值,后跟文字 _ 替换正则表达式匹配的内容,这实际上替换了第二个 @987654338 @ 带有_

    • 如果给定的文件名与正则表达式不匹配(如果它已经正确),则按原样返回名称,这在 Rename-Item 的上下文中是一个安静的空操作。

    【讨论】:

      【解决方案2】:

      看看你的例子,第二个- 似乎总是出现在数字之间。类似$Variable -replace 'REGEX','_'

      使用下面的正则表达式将匹配那些。

      (?<=[0-9])(.)(?=[0-9])
      

      () 创建一个组来匹配,它是一个捕获组。

      ?&lt;= 是一个正向的lookbehind,它匹配主表达式之前的一个组,而不包括在结果中

      [0-9] 是字符集,匹配 0 到 9 之间的任何值。

      . 匹配除换行符以外的任何字符

      ?= 是正向前瞻,它匹配主表达式之后的组,而不包括在结果中

      我建议使用Regexr 来测试和学习正则表达式。

      【讨论】:

      • 不幸的是,并非总是在数字之间。有时像这样 E21U-50A_E21U-50-CIPP-PST-CMP
      【解决方案3】:

      您可以在- 的前两次出现处拆分字符串,然后通过-_ 连接它们:

      $name = '01A-50-02A-50-CIPP-PRE.MP4'
      $first,$second,$rest = $name -split '-',3
      $newName = "${first}-${second}_${rest}"
      

      【讨论】:

      • 出于某种原因,'{0}-{1}_{2}' -f $first, $second, $rest 对我来说似乎更好。 [咧嘴一笑]
      【解决方案4】:

      这个 RegEx:(?&lt;=(^|\n)[^-]*-[^-]*)- 怎么样?

      或作为完整命令(使用Replace Part of File Name Powershell 的答案):

      Get-ChildItem | Rename-Item -NewName {$_.name -replace '(?<=^[^-_]+-[^-_]+)-','_'}
      

      编辑:incorporated suggestions from @mklement0

      【讨论】:

      • 成功了!这就是我想要做的。
      【解决方案5】:

      谢谢所罗门·乌科! 这几乎正​​是我想要的。

      获取子项 | Rename-Item -NewName {$.name -replace '(?'}

      它在我可以扔给它的所有示例上都非常有效,除了... 如果我在一组错误命名和正确命名的文件上运行代码,它会在它不属于的地方添加另一个下划线......

      "E21U-50A_E21U_50-CIPP-PST-CMP"
      

      而不是

      "E21U-50A_E21U-50-CIPP-PST-CMP"
      

      解决这个问题很简单。
      我所做的只是首先将所有_s 替换为-s。

      Get-ChildItem | Rename-Item -NewName {$_.name -replace '_','-'}
      
      Get-ChildItem | Rename-Item -NewName {$_.name -replace '(?<=(^|\n)[^-]*-[^-]*)-','_'}
      

      感谢所有有其他想法的人。诚然,我没有尝试过它们,因为这个解决方案是我尝试的第一个解决方案,并且成功了。
      但是,我会在完成工作后修改其他解决方案。
      再次感谢。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-10-07
        • 1970-01-01
        • 2021-11-12
        • 2021-09-24
        • 1970-01-01
        • 2016-11-02
        • 1970-01-01
        相关资源
        最近更新 更多