使用 Powershell 将第二次出现的“-”替换为“_”
Posted
技术标签:
【中文标题】使用 Powershell 将第二次出现的“-”替换为“_”【英文标题】:Replacing 2nd occurrence of "-" with "_" using 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 中。
对此的任何帮助将不胜感激。
【问题讨论】:
【参考方案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])
()
创建一个组来匹配,它是一个捕获组。
?<=
是一个正向的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:(?<=(^|\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)[^-]*-[^-]*)-','_'
感谢所有有其他想法的人。诚然,我没有尝试过它们,因为这个解决方案是我尝试的第一个解决方案,并且成功了。 但是,我会在完成工作后修改其他解决方案。 再次感谢。
【讨论】:
以上是关于使用 Powershell 将第二次出现的“-”替换为“_”的主要内容,如果未能解决你的问题,请参考以下文章