2014-02-14 37 views
1

分裂模块通常用来分割的Active Directory专有名称和规范的名称来的RDN方便地忘记了,可能在组织单位和中枢神经系统被用作逃跑的分隔符:(PowerShell中)分割字符串转义分隔符

与转义逗号的专有名称示例:

CN=Test User,OU=Comma\,Test,OU=Test,DC=domain,DC=com 

规范名称例如使用转义斜杠:

Domain.com/Test/Slash\/Test/Test User 

在互联网上有几个分裂的例子,甚至没有提到这个陷阱,它可能会工作很长一段时间,但迟早会对解决这个编程缺陷造成很大的痛苦。

我不认为有一种简单的方法可以使用正则表达式正确拆分转义字符串(另请参阅:是否存在包含转义序列的字符串的纯正则表达式?)。 。

回答

1

总结和补充现有的,有用的答案:

  • mjolinor's answer效果很好,如果你不用担心\\在输入显示为转义\
    如果存在\\,解决方案会误解中的,为转义(而不是转义的\后跟未转义的,)。

  • iRon's own answer解决了问题与更复杂的正则表达式。

此外,您可能要删除转义字符分裂后;建设铁的正则表达式并添加-replace操作与正则表达式\\(.)

> 'foo,bar\,baz,bang\\,last' -split '(?<![^\\](\\\\)*\\),' -replace '\\(.)', '$1' 
foo 
bar,baz 
bang\ 
last 

这里有一个简单的效用函数一个包装上面,有一个可配置的分离和逃避焦炭:

function Split-Text { 
    param(
    [Parameter(Mandatory=$True)] [string] $Text, 
    [Parameter(Mandatory=$True)] [string] $Separator, 
    [string] $EscapeChar = '\' 
) 
    $Text -split 
    ('(?<![^{0}]({0}{0})*{0}){1}' -f [regex]::Escape($EscapeChar), [regex]::Escape($Separator)) ` 
     -replace ('{0}(.)' -f [regex]::Escape($EscapeChar)), '$1' 
} 
# Sample call - yields the same as above. 
Split-Text 'foo,bar\,baz,bang\\,last' ',' 

# With "/" as the separator - same output. 
Split-Text 'foo/bar\/baz/bang\\/last' '/' 
0

所以我创建了一个小的cmdlet,增加了一个逃生功能,将现有分裂模块:

Function Split { 
    param(
     [Parameter(Mandatory = $True, ValueFromPipeline = $true)][String]$String, 
     [Parameter(Mandatory = $False, Position = 0)][String]$Delimiter = " ", 
     [Parameter(Mandatory = $False, Position = 1)][Int]$MaxSubstrings = 0, 
     [Parameter(Mandatory = $False, Position = 2)][String]$Escape, 
     [Parameter(Mandatory = $False, Position = 3)][String]$Options = "" 
    ) 
    If ($Escape) {$String = $String.Replace("$Escape$Delimiter", [String][Char]27)} 
    $Split = $String -Split $Delimiter, $MaxSubstrings, $Options 
    If ($Escape) {$Split | ForEach {$_.Replace([String][Char]27, "$Escape$Delimiter")}} Else {$Split} 
} 

"CN=Test User,OU=Comma\,Test,OU=Test,DC=domain,DC=com" | Split "," -Escape "\" 
"Domain.com/Test/Slash\/Test/Test User" | Split "/" -Escape "\" 
4

使用负回顾后:

$text = 'CN=Test User,OU=Comma\,Test,OU=Test,DC=domain,DC=com' 
$text -split '(?<!\\),' 

CN=Test User 
OU=Comma\,Test 
OU=Test 
DC=domain 
DC=com 

$text = 'Domain.com/Test/Slash\/Test/Test User' 
$text -split '(?<!\\)/' 

Domain.com 
Test 
Slash\/Test 
Test User 
+0

我曾经见过这个答案,但之前无法使用它。但显然,我犯了一个错字,因为它现在起作用了。 -谢谢 – iRon

1

我觉得还是有点陷阱因为RND可能会以反斜杠结尾(这将会以额外的反斜杠转义):

$text = 'CN=Test User,OU=EndSlash\\,OU=Comma\,Test,DC=domain,DC=com' 
$text -split '(?<!\\),' 
CN=Test User 
OU=EndSlash\\,OU=Comma\,Test 
DC=domain 
DC=com 

换句话说,只有当前面有奇数个反斜杠时,才应该跳过相关的分隔符。为了说明这一点,我认为完整的正则表达式应该是: (?<![^\\](\\\\)*\\),(用于专有名称)和 (?<![^\\](\\\\)*\\)/(用于规范名称)。

$text = 'CN=Test User,OU=EndSlash\\,OU=Comma\,Test,DC=domain,DC=com' 
$text -split '(?<![^\\](\\\\)*\\),' 
CN=Test User 
OU=EndSlash\\ 
OU=Comma\,Test 
DC=domain 
DC=com 

$text = 'Domain.com/Slash\/Test/EndSlash\\/Test/Test User' 
$text -split '(?<![^\\](\\\\)*\\)/' 
Domain.com 
Slash\/Test 
EndSlash\\ 
Test 
Test User