替换第二个和第三个下划线之间的任何内容

时间:2018-10-15 09:31:30

标签: regex powershell

我有一个PowerShell脚本行,该脚本行用“ _”替换(删除)第二个和第三个下划线之间的字符:

get-childitem *.pdf | rename-item -newname { $_.name -replace '_\p{L}+, \p{L}+_', "_"}

示例:

12345_00001_LastName, FirstName_09_2018_Text_MoreText.pdf
12345_00002_LastName, FirstName-SecondName_09_2018_Text_MoreText.pdf
12345_00003_LastName, FirstName SecondName_09_2018_Text_MoreText.pdf

_\p{L}+, \p{L}+_正则表达式仅适用于第一个示例。为了替换之间的所有内容,我使用了_(?:[^_]*)_([^_]*)_(根据regex101,这几乎可以正常工作),但是输出为:

12345_09_MoreText.pdf

所需的输出将是:

 12345_00001_09_2018_Text_MoreText.pdf
 12345_00002_09_2018_Text_MoreText.pdf
 12345_00003_09_2018_Text_MoreText.pdf

如何正确地用“ _”替换第二个和第三个下划线以及它们之间的所有内容?

4 个答案:

答案 0 :(得分:3)

如果您不想使用正则表达式-

$files = get-childitem *.pdf        #get all pdf files
$ModifiedFiles, $New = @()  #declaring two arrays
foreach($file in $files)
{
    $ModifiedFiles = $file.split("_")
    $ModifiedFiles = $ModifiedFiles | Where-Object { $_ -ne $ModifiedFiles[2] }     #ommitting anything between second and third underscore
    $New = "$ModifiedFiles" -replace (" ", "_")
    Rename-Item -Path $file.FullName -NewName $New
}

样本数据-

$files = "12345_00001_LastName, FirstName_09_2018_Text_MoreText.pdf", "12345_00002_LastName, FirstName-SecondName_09_2018_Text_MoreText.pdf", "12345_00003_LastName, FirstName SecondName_09_2018_Text_MoreText.pdf"
$ModifiedFiles, $New = @()  #declaring two arrays
foreach($file in $files)
{
    $ModifiedFiles = $file.split("_")
    $ModifiedFiles = $ModifiedFiles | Where-Object { $_ -ne $ModifiedFiles[2] }     #ommitting anything between second and third underscore
    $New = "$ModifiedFiles" -replace (" ", "_")
}

答案 1 :(得分:2)

您可以使用

-replace '^((?:[^_]*_){2})[^_]+_', '$1'

请参见regex demo

详细信息

  • ^-行首
  • ((?:[^_]*_){2})-第1组(替换模式中的值将用$1引用):重复两次
    • [^_]*-除下划线外的0+个字符
    • _-下划线
  • [^_]+-除_以外的1个或更多字符
    • _-下划线

答案 2 :(得分:2)

这是使用字符串方法的另一种方法。

'12345_00003_LastName, FirstName SecondName_09_2018_Text_MoreText.pdf'.
    Split('_').
    Where({
        $_ -notmatch ','
        }) -join '_'

结果= 12345_00003_09_2018_Text_MoreText.pdf

具有以下功能...

  • 下划线
  • 扔掉其中任何带有逗号的项目
  • 将其余项目重新连接到带下划线的字符串中

我怀疑纯正则表达式解决方案会更快,但是您可能只想使用它,以便在下次需要修改它时更容易理解。 [咧嘴]

答案 3 :(得分:2)

提供避免复杂正则表达式的替代解决方案:以下内容基于-split-join运算符,并展示了PowerShell在数组切片方面的灵活性:

Get-ChildItem *.pdf | Rename-Item { ($_.Name -split '_')[0..1 + 3..6] -join '_' } -WhatIf
  • $_.Name -split '_'将文件名按_拆分为令牌(子字符串)数组。
  • 数组切片[0..1 + 3..6]结合了两个范围表达式(..),从本质上从数组中删除了索引为2的标记。
  • -join '_'将修改后的数组重新组合成一个_分隔的字符串,从而产生所需的结果。

注意:6是数组的上限,在上面进行了硬编码,虽然次优,但对于这种情况下的可预测输入,已足够。

从Windows PowerShell v5.1 / PowerShell Core 6.1.0开始,为了动态地确定上限 ,您需要一个辅助变量的帮助,该变量很笨拙:

Get-ChildItem *.pdf |
  Rename-Item { ($arr = $_.Name -split '_')[0..1 + 3..($arr.Count-1)] -join '_' } -WhatIf

如果我们改为写[0..1 + 3..]会不会很好? this feature suggestion on GitHub的主题是对PowerShell切片语法的这项改进和其他改进。

相关问题