string - Powershell脚本替换由于 “(”或 “)”而导致的路径字符串中的字符错误

标签 string powershell replace rename-item-cmdlet

我编写了一个Powershell脚本,该脚本接收N个字符,这些字符必须由用户的另一个给定字符替换。例如,用户想要替换(,)和-。用户通过此循环输入必须替换的字符:

#Declare array for special characters to replace
$replaceChars = @( )

#Instruct the user about entering characters to replace
Write-Host
Write-Host "Please enter what you would like to replace in your names. This can contain one or more characters. Example: (2) or ^ or _" -ForegroundColor Cyan
Write-Host "Enter -1 to end your input and continue." -ForegroundColor Cyan

#Get values until sentinal is passed
$input = "" #input from user declared to blank

#loop for special characters
while($input -ne -1) {

    #get the input from the user
    $input = Read-Host -Prompt "Enter what you would like to replace (-1 to finish)"

    #if the input isn't sentinal, put it in the replaceChars array
    if($replaceChars.Length -gt 0 -and $input -eq -1) {
        Write-Host
        Write-Host "Your entries have been stored." -ForegroundColor Green
    } #end-if
    elseif($replaceChars.Length -eq 0 -and $input -eq -1) {
        Write-Host
        Write-Host "ERROR: You must enter at least one character to continue." -ForegroundColor Red
        $input = $NULL
    }
    elseif($input -eq '') {
    Write-Host
    Write-Host "Invalid entry. Entry cannot be blank, please enter a value." -ForegroundColor Red
    }#end-elseif
    elseif($input.IndexOfAny([System.IO.Path]::GetInvalidFileNameChars()) -ge 0) {
        Write-Host
        Write-Host "Invalid entry. File names cannot contain / \ : * ? `" < > |" -ForegroundColor Red
    }#end-elseif
    else {
        $replaceChars += $input
    } #end-else

}#end-while

然后,用户通过以下代码输入替换字符:
#Get the char to replace to
Write-Host
Write-Host "Please enter what you want to replace the selected characters with. Leave blank and hit enter to delete the old characters." -ForegroundColor Cyan
$newChar = Read-Host -Prompt "Please enter new character(s)"
while($newChar.IndexOfAny([System.IO.Path]::GetInvalidFileNameChars()) -ge 0) {
    Write-Host
    Write-Host "The entry is invalid for file names. File names cannot contain / \ : * ? `" < > |" -ForegroundColor Red
    $newChar = Read-Host -Prompt "Please enter new character(s)"
}
Write-Host
Write-Host "New character has been stored" -ForegroundColor Green

然后,我正在处理条目:
#Iterate through each character 
foreach($char in $replaceChars) {
    if($type -eq 1) {
        gci -File -Path "$path" | Where-Object { $_.Name -match $char } | ForEach-Object { $_ | rename-item  -NewName $_.Name.Replace($char, $newChar) }
    } elseif ($type -eq 2) { #end-if
        gci -Directory -Path "$path" | Where-Object { $_.Name -match $char } | ForEach-Object { $_ | rename-item  -NewName $_.Name.Replace($char, $newChar) }
    } else { #end-elseif 
        gci -Path "$path" | Where-Object { $_.Name -match $char } | ForEach-Object { $_ | rename-item  -NewName $_.Name.Replace($char, $newChar) }
    }#end-else
} #end-foreach

错误:如果用户输入类似(或)的内容,则脚本的最后一部分将失败,并显示以下错误代码:
parsing "(" - Not enough )'s.
At <path to script>:109 char:50
+ ... gci -File -Path "$path" | Where-Object { $_.Name -match $char } | For ...
+                                              ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException

我的解决方案:我试图使用[regex]::Escape()逃脱$char$newChar变量来修复括号错误。我也试图通过用单引号和双引号引起来的变量来解决这个问题。但是,这防止了实际字符替换的发生。我知道括号/特殊字符是导致此问题的原因,因此我需要以某种方式进行转义;但是,[regex]::Escape()解决方案破坏了字符匹配,最终导致不替换用户输入的任何字符。

我的问题:如何成功转义GCI cmdlet中的$char$newChar变量,并仍然替换特殊字符(如(或))
gci -Path "$path" | Where-Object { $_.Name -match $char } | ForEach-Object { $_ | rename-item  -NewName $_.Name.Replace($char, $newChar) }

最佳答案

您如何尝试完全实现[regex]::Escape()?如果您尝试先保存$char以便逃脱,我会看到您的问题。由于您的.replace()方法不使用正则表达式。这应该给您一些选择

  • 只需更新where子句以将转义符用于比较即可。那$char不会永久更改。无论您打算使用-match还是不支持正则表达式字符,这都是一个好主意。
    gci -Path "$path" | Where-Object { $_.Name -match [regex]::Escape($char) } | ...
    
  • $char保存为转义符,并使用还支持正则表达式的-replace运算符。
    gci -Path "$path" | Where-Object { $_.Name -match $char } | 
        ForEach-Object { $_ | rename-item  -NewName ($_.Name -replace $char, $newChar)) 
    
  • 完全不使用正则表达式运算符
    gci -Path "$path" | Where-Object { $_.Name.Contains($char) } | ...
    


  • 几点评论
  • 不要使用名称$input。它是保留的变量名。参见about_automatic_variables
  • 由于您正在使用文件的全名,因此我警告您也可能不小心编辑了文件的扩展名。在这种情况下,basename属性可能对您有用。
  • 正如TheMadTechnician所指出的,您可以通过在Get-ChildItem级别进行过滤来避免正则表达式/非正则表达式问题。
    gci -Path "$path" -Filter "*$char*" | Rename-Item  -NewName {$_.Name.Replace($char, $newChar)}
    
  • 关于string - Powershell脚本替换由于 “(”或 “)”而导致的路径字符串中的字符错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46855087/

    相关文章:

    python - 我们如何在一行中使用空格输入原始输入,然后将它们转换为整数并将它们添加到列表中?

    date - 在PowerShell中设置System.DateTime对象的时间

    powershell - 处理来自 powershell 的 SOAP 请求

    powershell - Close-SMBOpenFile 抛出错误并且未在 try-catch 中捕获

    Python:将 "\"更改为 "\\"

    regex - 正则表达式 - 以字符串开头和结尾

    swift - 如何检查句子是否包含特定单词?

    algorithm - 将一个字符串更改为另一个字符串的简单突变的数量?

    python - 在 Pandas 数据框中填充一列字符串

    regex - 如何使用 Perl 将以下字符串中的逗号替换为 & ?