Powershell并通过select-string -Allmatches(2.0)传递元字符

时间:2012-05-17 13:18:36

标签: regex powershell

我正在尝试编写/修改一个函数来清理Windows文件系统上的非法文件名(由我们网络的OS X客户端放置)。该脚本工作正常,但是当尝试在正则表达式中传递某些元字符时,在-AllMatches中执行的检查会返回false以进行肯定匹配(使用有意为非法测试的文件夹)。如果字符是单独完成的(不使用提供的循环),则返回true。我已经尝试了各种逃避方法(以及两者的组合,\和`),没有运气。其他特殊字符工作正常(例如&)。

任何人都有任何想法为什么这样做? (注意:下面注释掉的非法字符的两个声明被分解为不起作用的字符和字符。

function Check-IllegalCharacters ($Path, [switch]$Fix, [switch]$Verbose)
{
Write-Host Checking files in $Path, please wait...
#Get all files and folders under the path specified
$items = Get-ChildItem -Path $Path -Recurse
foreach ($item in $items)
{
    #Check if the item is a file or a folder
    if ($item.PSIsContainer) { $type = "Folder" }
    else { $type = "File" }

    #Report item has been found if verbose mode is selected
    if ($Verbose) { Write-Host Found a $type called $item.FullName }

    #Check if item name is 128 characters or more in length
    if ($item.Name.Length -gt 127)
    {
        Write-Host $type $item.Name is 128 characters or over and will need to be truncated -ForegroundColor Red
    }
    else
    {
    #$illegalChars = '[<>?*|/\:"]'    $illegalChars = '[&{}~#%]'
        #Got this from http://powershell.com/cs/blogs/tips/archive/2011/05/20/finding-multiple-regex-matches.aspx
        $illegalChars = '[&{}~#%]'
        filter Matches($illegalChars)
        {
            $item.Name | Select-String -AllMatches $illegalChars |
            Select-Object -ExpandProperty Matches
            Select-Object -ExpandProperty Values

        }

        #Replace illegal characters with legal characters where found
        $newFileName = $item.Name
        Matches $illegalChars | ForEach-Object {
            Write-Host $type $item.FullName has the illegal character $_.Value -ForegroundColor Red
            #These characters may be used on the file system but not SharePoint
            if ($_.Value -match "&") { $newFileName = ($newFileName -replace "&", "and") }
            if ($_.Value -match "{") { $newFileName = ($newFileName -replace "{", "(") }
            if ($_.Value -match "}") { $newFileName = ($newFileName -replace "}", ")") }
            if ($_.Value -match "~") { $newFileName = ($newFileName -replace "~", "-") }
            if ($_.Value -match "#") { $newFileName = ($newFileName -replace "#", "") }
            if ($_.Value -match "%") { $newFileName = ($newFileName -replace "%", "") }
        }

        #Check for start, end and double periods
        if ($newFileName.StartsWith(".")) { Write-Host $type $item.FullName starts with a period -ForegroundColor red }
        while ($newFileName.StartsWith(".")) { $newFileName = $newFileName.TrimStart(".") }
        if ($newFileName.EndsWith(".")) { Write-Host $type $item.FullName ends with a period -ForegroundColor Red }
        while ($newFileName.EndsWith("."))   { $newFileName = $newFileName.TrimEnd(".") }
        if ($newFileName.Contains("..")) { Write-Host $type $item.FullName contains double periods -ForegroundColor red }
        while ($newFileName.Contains(".."))  { $newFileName = $newFileName.Replace("..", ".") }

        #Fix file and folder names if found and the Fix switch is specified
        if (($newFileName -ne $item.Name) -and ($Fix))
        {
            Rename-Item $item.FullName -NewName ($newFileName)
            Write-Host $type $item.Name has been changed to $newFileName -ForegroundColor Blue
        }
    }
}
}

非常感谢有人能提供帮助!

编辑:为了进一步说明,此处的函数可以正常工作,只有在将正则表达式表达式(并在必要时转义)更改为其他变量时才会起作用$ illegalChars ='[&lt;&gt;?* | / \: “]'它不再正常运行。它会运行得很好,没有错误,但它不会捕获任何带有这些字符的文件或文件夹。

可以加载该函数,然后执行'Check-IllegalCharacters -Path $ path -Verbose'

1 个答案:

答案 0 :(得分:0)

正如您在下面的示例中所看到的,当caracter是Regex元字符时,您必须在替换运算符的左侧使用'\'。切换-regex选项可以为您提供帮助。

clear-host
$stringTotest = "coucou & Bonjour {vous} [<>?*|/\:`"]"

switch -regex ($stringTotest)
{
    "&"
  {
        $stringTotest = $stringTotest -replace '&', 'et'
    }
    "{"
  {
        $stringTotest = $stringTotest -replace '{', '('
    }
    "{"
  {
        $stringTotest = $stringTotest -replace '}', ')'
    }
    "\["
  {
        $stringTotest = $stringTotest -replace '\[', '1'
    }
    "<"
  {
        $stringTotest = $stringTotest -replace '<', '2'
    }
    ">"
  {
        $stringTotest = $stringTotest -replace '>', '3'
    }
    "\?"
  {
        $stringTotest = $stringTotest -replace '\?', '4'
    } 
    "\*"
  {
        $stringTotest = $stringTotest -replace '\*', '5'
    }
    "\|"
  {
        $stringTotest = $stringTotest -replace '\|', '6'
    }
    "/"
  {
        $stringTotest = $stringTotest -replace '/', '7'
    }  
    "\\"
  {
        $stringTotest = $stringTotest -replace '\\', '8'
    }    
    ":"
  {
        $stringTotest = $stringTotest -replace ':', '9'
    }      
    "`""
  {
        $stringTotest = $stringTotest -replace '"', '0'
    }    
    "\]"
  {
        $stringTotest = $stringTotest -replace '\]', '1'
    }    
    default
  {
        break
    }
}

$stringTotest