2014-02-14 39 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