我有一个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
如何正确地用“ _”替换第二个和第三个下划线以及它们之间的所有内容?
答案 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切片语法的这项改进和其他改进。