Powershell:从 LDIF 文件中提取模式之间的值

Powershell: Extract value between pattern from a LDIF file

我正在研究正则表达式,我的任务是编写一个脚本来提取 LDIF 上搜索模式之间的特定文本,我 运行 遇到了一些问题。我们从中获得的 LDIF 是 OpenLDAP 格式,因此我们拥有的文件是

dn: cn=user1,ou=department,o=company,c=root
changetype: add
givenName: Givenname1
sn: SN1
Country: Cn1
userCertificate;binary:: lowhjsefnasdvonidfb8943th54ebghyLHFUn9894y9bKalkbjsf
 89ehgvpnoLNGPOVNnl;aiorgpnsg;n\vbubGB*gpbeoabgpiobrgaragop08hgnaoergn9r0agnh
 U0hBMjU2MB4XDTE5MDYwNTA3lowhjsefnasdvonidfb8943th54ebghyLHFUn9894y9bKalkbjsf
 89ehgvpnoLNGPOVNnl;aiorgpnsg;n\vbubGB*gpbeoabgpiobrgaragop08hgnaoergn9r0agnh
 U0hBMjU2MB4XDTE5MDYwNTA3lowhjsefnasdvonidfb8943th54ebghyLHFUn9894y9bKalkbjsf
 89ehgvpnoLNGPOVNnl;aiorgpnsg;n\vbubGB*gpbeoabgpiobrgaragop08hgnaoergn9r0agnh
 U0hBMjU2MB4XDTE5MDYwNTA3lowhjsefnasdvonidfb8943th54ebghyLHFUn9894y9bKalkbjsf
 89ehgvpnoLNGPOVNnl;aiorgpnsg;n\vbubGB*gpbeoabgpiobrgaragop08hgnaoergn9r0agnh
 U0hBMjU2MB4XDTE5MDYwNTA3
City: City1

dn: cn=user3,ou=department3,o=company,c=root
changetype: add
givenName: Givenname3
sn: SN3
customdn: cn=user3,ou=department3,o=company,c=root
userCertificate;binary:: lowhjsefnasdvonidfb8943th54ebghyLHFUn9894y9bKalkbjsf
 89ehgvpnoLNGPOVNnl;aiorgpnsg;n\vbubGB*gpbeoabgpiobrgaragop08hgnaoergn9r0agnh
 U0hBMjU2MB4XDTE5MDYwNTA3lowhjsefnasdvonidfb8943th54ebghyLHFUn9894y9bKalkbjsf
 89ehgvpnoLNGPOVNnl;aiorgpnsg;n\vbubGB*gpbeoabgpiobrgaragop08hgnaoergn9r0agnh
 U0hBMjU2MB4XDTE5MDYwNTA3lowhjsefnasdvonidfb8943th54ebghyLHFUn9894y9bKalkbjsf
 89ehgvpnoLNGPOVNnl;aiorgpnsg;n\vbubGB*gpbeoabgpiobrgaragop08hgnaoergn9r0agnh
 U0hBMjU2MB4XDTE5MDYwNTA3lowhjsefnasdvonidfb8943th54ebghyLHFUn9894y9bKalkbjsf
 89ehgvpnoLNGPOVNnl;aiorgpnsg;n\vbubGB*gpbeoabgpiobrgaragop08hgnaoergn9r0agnh
 U0hBMjU2MB4XDTE5MDYwNTA3
Country: Cn3
City: City3

dn: cn=user2,ou=department,o=company,c=root
changetype: add
givenName: Givenname2
sn: SN2
customdn: cn=user2,ou=department,o=company,c=root
userCertificate;binary:: lowhjsefnasdvonidfb8943th54ebghyLHFUn9894y9bKalkbjsf
 89ehgvpnoLNGPOVNnl;aiorgpnsg;n\vbubGB*gpbeoabgpiobrgaragop08hgnaoergn9r0agnh
 U0hBMjU2MB4XDTE5MDYwNTA3lowhjsefnasdvonidfb8943th54ebghyLHFUn9894y9bKalkbjsf
 89ehgvpnoLNGPOVNnl;aiorgpnsg;n\vbubGB*gpbeoabgpiobrgaragop08hgnaoergn9r0agnh
 U0hBMjU2MB4XDTE5MDYwNTA3lowhjsefnasdvonidfb8943th54ebghyLHFUn9894y9bKalkbjsf
 89ehgvpnoLNGPOVNnl;aiorgpnsg;n\vbubGB*gpbeoabgpiobrgaragop08hgnaoergn9r0agnh
 U0hBMjU2MB4XDTE5MDYwNTA3lowhjsefnasdvonidfb8943th54ebghyLHFUn9894y9bKalkbjsf
 89ehgvpnoLNGPOVNnl;aiorgpnsg;n\vbubGB*gpbeoabgpiobrgaragop08hgnaoergn9r0agnh
 U0hBMjU2MB4XDTE5MDYwNTA3
Country: Cn1
City: City1

文件行由换行符 (CRLF) 分隔。因此,我尝试使用以下模式仅为 User3 提取文本,这似乎给我空白文件。

$RegexPattern = "`r`ndn: cn=User3(.*?)`r`n`r`n"
$result = [regex]::match($inputfile,$RegexPattern).Groups[1].Value

如果我将捕获模式从更改为 (.*),我会在第一次匹配后获取所有文本。很确定我遗漏了一些东西,但就是看不到我遗漏了什么。有好心人帮忙吗?

编辑:也添加了一些关于自定义 DN 的附加信息。在 dn: 的搜索字符串中包含 CRLF 的原因是因为用户对象上还有一个自定义 DN,它是用于向后兼容的 dn 属性的副本。我已经用这个属性更新了上面的示例 LDIF 条目。 编辑 2:Wiktor 的正则表达式几乎可以工作,直到代码偶然发现 userCertificate 属性,其中多个属性仅用 LF 分割,而不是在其他地方看到的 CR+LF。

首先,确保将整个文件读入变量:

$inputfile = Get-Content .\input.ldif -Raw

然后,你需要一个像

这样的正则表达式
$RegexPattern = '(?mi)^dn: cn=User3[^\r\n]*(?:\r?\n[^\r\n]+)*'
$result = [regex]::match($inputfile,$RegexPattern).Value

regex demo

详情

  • (?mi) - 不区分大小写的匹配开启并且多行行为也开启
  • ^ - 行首
  • dn: cn=User3 - 文字文本
  • [^\r\n]* - 除了 CR 和 LF
  • 之外的 0+ 个字符
  • (?:\r?\n[^\r\n]+)* - CRLF/LF 出现 0+ 次,然后是 CR 和 LF 以外的 1+ 个字符(因此,上述字符串下方的任何非空行)。

另一种方法是将文件作为单个字符串读取,分成 2 个(或更多)换行符并使用 Where-Object 子句来获取以 dn: cn=user3.[=14= 开头的文本块]

(Get-Content -Path 'D:\Test\openLDAP.ldif' -Raw) -split '(\r?\n){2,}' | 
 Where-Object { $_.Trim() -match "^dn: cn=user3" }

结果:

dn: cn=user3,ou=department3,o=company,c=root
changetype: add
givenName: Givenname3
sn: SN3
Country: Cn3
City: City3