用于替换路径字符串中的字符的 Powershell 脚本因“(”或“)”而出错
Powershell Script to replace characters in path strings errors out due to "(" or ")"
我编写了一个 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
变量来修复括号错误。我还试图通过用单引号和双引号括起变量来解决这个问题;但是,这会阻止实际的字符替换发生。我知道 parentheses/special 字符是导致问题的原因,我需要以某种方式转义这些字符;然而,[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()
的?如果您尝试在转义前 save $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 级别进行过滤来避免 regex/non-regex 问题。
gci -Path "$path" -Filter "*$char*" | Rename-Item -NewName {$_.Name.Replace($char, $newChar)}
解决方案: 我已经实施了@Matt 的建议并通过以下方式解决了错误:
#Iterate through each character
foreach($char in $replaceChars) {
if($type -eq 1) {
gci -File -Path "$path" | Where-Object { $_.Basename.Contains($char) } | ForEach-Object { $_ | rename-item -NewName ($_.Basename.Replace($char, $newChar) + $_.extension) }
} elseif ($type -eq 2) { #end-if
gci -Directory -Path "$path" | Where-Object { $_.Basename.Contains($char) } | ForEach-Object { $_ | rename-item -NewName ($_.Basename.Replace($char, $newChar) + $_.extension) }
} else { #end-elseif
gci -Path "$path" | Where-Object { $_.Basename.Contains($char) } | ForEach-Object { $_ | rename-item -NewName ($_.Basename.Replace($char, $newChar) + $_.extension) }
}#end-else
} #end-foreach
我编写了一个 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
变量来修复括号错误。我还试图通过用单引号和双引号括起变量来解决这个问题;但是,这会阻止实际的字符替换发生。我知道 parentheses/special 字符是导致问题的原因,我需要以某种方式转义这些字符;然而,[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()
的?如果您尝试在转义前 save $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 级别进行过滤来避免 regex/non-regex 问题。
gci -Path "$path" -Filter "*$char*" | Rename-Item -NewName {$_.Name.Replace($char, $newChar)}
解决方案: 我已经实施了@Matt 的建议并通过以下方式解决了错误:
#Iterate through each character
foreach($char in $replaceChars) {
if($type -eq 1) {
gci -File -Path "$path" | Where-Object { $_.Basename.Contains($char) } | ForEach-Object { $_ | rename-item -NewName ($_.Basename.Replace($char, $newChar) + $_.extension) }
} elseif ($type -eq 2) { #end-if
gci -Directory -Path "$path" | Where-Object { $_.Basename.Contains($char) } | ForEach-Object { $_ | rename-item -NewName ($_.Basename.Replace($char, $newChar) + $_.extension) }
} else { #end-elseif
gci -Path "$path" | Where-Object { $_.Basename.Contains($char) } | ForEach-Object { $_ | rename-item -NewName ($_.Basename.Replace($char, $newChar) + $_.extension) }
}#end-else
} #end-foreach