Regex 替换无效的文件名字符
我想写一个小的实用程序函数,用破折号替换文件名中的任何禁止字符序列 例如:Regex 替换无效的文件名字符,regex,powershell,Regex,Powershell,我想写一个小的实用程序函数,用破折号替换文件名中的任何禁止字符序列 例如: foo.txt==>foo.txt 一些字符串\o/==>一些字符串-o- https://stackoverflow.com/questions==>https stackoverflow.com问题 我这样写函数: function Get-SafeFileName{ param( [Parameter(Mandatory, Position=0, ValueFromPipeline)]
==>foo.txt
foo.txt
==>一些字符串\o/
一些字符串-o-
==>https://stackoverflow.com/questions
https stackoverflow.com问题
function Get-SafeFileName{
param(
[Parameter(Mandatory, Position=0, ValueFromPipeline)]
[object]$Data
)
process {
$pattern = "[" + [regex]::Escape([string][System.IO.Path]::GetInvalidFileNameChars()) +"]+"
[regex]::Replace($Data, $pattern, "-")
}
}
这是可行的,除了空格字符被替换,即使它是允许的字符
这是一个字符串
导致这是一个字符串
,这是不必要的
如何解决这个问题
挖掘一点显示[System.IO.Path]::GetInvalidFileNameChars()
不包含空格字符(ascii代码32)。但还有许多其他类似于“空间”的角色
也许正则表达式引擎没有看到区别?首先,通过将无效字符列表转换为字符串(即字符类中出现空格的位置)来错误地转换无效字符列表 其次,您不能使用
Regex.Escape
来转义进入字符类的字符,因为这意味着转义字符必须是字符类之外的文字
解决办法是
function Get-SafeFileName{
param(
[Parameter(Mandatory, Position=0, ValueFromPipeline)]
[object]$Data
)
process {
$pattern = '[' + ([System.IO.Path]::GetInvalidFileNameChars() -join '').Replace('\','\\') + ']+'
[regex]::Replace($Data, $pattern, "-")
}
}
在字符类中需要转义的字符只有:
^
-
\
]
由于
GetInvalidFileNameChars()
只包含上述四个特殊字符中的一个,因此您可以只使用一个.Replace('\','\')
而不是所有四个.Replace('\','\').Replace('-','\-').Replace('^','\^').Replace(']','\]'))
我找到了另一种使用unicode结构的方法
function Get-SafeFileName{
param(
[Parameter(Mandatory, Position=0, ValueFromPipeline)]
[object]$Data
)
process {
$pattern = "[" + ( ([System.IO.Path]::GetInvalidFileNameChars() | % { "\x" + ([int]$_).ToString('X2') } ) -join '') +"]+"
[regex]::Replace($Data, $pattern, "-")
}
}
$pattern
现在是[\x22\x3C\x3E\x7C\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1E\x1F\x3A\x3A\x3A\x5C\x5f]+>
有了这一点,就没有什么模棱两可的了。标准空格不会被替换您永远不应该使用[regex]::Escape
来转义进入字符类的字符。您可以从另一个角度看它,并拥有一个允许的字符数组,如果不匹配,则替换为“-”?@WiktorStribiżew:我不明白you@DuchyWare:正则表达式很方便,因为有量词。特别是,我的正则表达式有一个leader+
,它实际上将一系列禁止的字符重新保存到一个破折号上(如url示例中的://
),请参见。不用于转义字符类中的字符。