PowerShell 替换在我的脚本的最后一行不起作用

PowerShell replace doesn't work in the last line in my script

我使用 PSVersion 5.1.19041.1320.

我正在获取 Windows 服务的安全描述符,并试图为特定用户(在 [=43 的示例中)替换其中的访问权限(在本例中为 'TEST') =]).

我的大体逻辑是:

  1. 获取服务的安全描述符
  2. 提取 'D:' 和 'S:' 之间的部分(使用正则表达式 '(?<=D:)(.*)(?=S:)')
  3. 提取经过身份验证的用户 (AU) 的访问权限(使用正则表达式 '(([^()]*))' )
  4. 替换访问权限
  5. Assemble 3. 和 2. 回到新的安全描述符

示例:

$user = 'AU'
[string]$newAccessRights = 'TEST'
$sddl = sc.exe sdshow wuauserv | Where-Object {$_}
$dacl = [RegEx]::Matches($sddl,'(?<=D:)(.*)(?=S:)') | ForEach-Object {$_.Value}
$dacl = $dacl -replace ([RegEx]::Matches($dacl,"(\([^()]*\))") | Where-Object {$_.Value.split(';')[-1] -eq "${user})"} | ForEach-Object {$_.Value.split(';')[2]}), $newAccessRights
$sddl -replace ([RegEx]::Matches($sddl,"(?<=D:)(.*)(?=S:\()") | ForEach-Object {$_.Value}), $dacl

我的期望是安全描述符:

D:(A;;CCLCSWRPLORC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)S:(AU;FA;CCDCLCSWRPWPDTLOSDRCWDWO;;;WD)

将替换为:

D:(A;;TEST;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)S:(AU;FA;CCDCLCSWRPWPDTLOSDRCWDWO;;;WD)

但事实并非如此: Example

我做错了什么? 为什么最后一个替换不起作用?

你可以使用

$sddl = $sddl -replace "(\((?:[^();]*;){2})\w+((?:;[^()]*)?;$user\))", "`$newAccessRights`"

参见regex demo详情:

  • (\((?:[^();]*;){2}) - 第 1 组 (</code>):一个 <code>( 字符,然后两次出现除 (、[=15= 之外的任意零个或多个字符] 和 ; 后跟 ; char
  • \w+ - 一个或多个单词字符(或者,[^;]* 匹配除 ; 字符以外的零个或多个字符,它也适用于此)
  • ((?:;[^()]*)?;$user\)) - 第 2 组 (</code>):<code>; 的可选序列,然后是 ( 和 [=15= 以外的任何零个或多个字符] 然后是 ;$user 变量和一个 ) 字符。

注意:如果$user没有特殊字符,则不需要Regex.Escape。否则,逃避它,[regex]::Escape($user)。如果 $newAccessRights 中有一个 $ 字符后跟一个数字,您也需要将其转义 $newAccessRights.Replace('$', '$$') (这可以在替换模式中使用它之前完成) .