regex powershell -匹配字符串,如果它有一个特定的字符,例如lastname_firstname不匹配lastname_firstname_middleinitail

piok6c0g  于 2023-05-08  发布在  Shell
关注(0)|答案(3)|浏览(212)

我正在尝试匹配只有一个下划线的字符串。Match当前正在查找lastname_firstname和lastname_firstname_middleinitail。我只想返回lastname_firstname并排除其他所有内容。
我试过-match "._." ".(_)." "._{1}" -like "*_*"也有同样的问题。
下面是我的代码中具有-match的部分

$newUsers = Get-ADUser -SearchBase "CN=Users,DC=atlantic,DC=county" -Filter {WhenCreated -ge $date7DaysAgo} | Where-Object {$_.name -match "._."}
pcrecxhr

pcrecxhr1#

我建议您使用LDAP执行部分过滤,以减少数据集,使代码更高效。(name=*_*)只会搜索name属性中至少包含一个_的用户,不包括那些没有_的用户。
对于第二层过滤,^[a-z]+_[a-z]+$将确保名称只有一个_,但也只有从az的字符,如果你需要更包容,即。名称可以是09,您可以使用^[a-z0-9]+_[a-z0-9]+$

$daysAgo = [datetime]::UtcNow.AddDays(-7).ToString('yyyyMMddHHmmss.0Z')

$getADUserSplat = @{
    SearchBase = 'CN=Users,DC=atlantic,DC=county'
    LDAPFilter = "(&(WhenCreated>=$daysAgo)(name=*_*))"
}

$newUsers = Get-ADUser @getADUserSplat |
    Where-Object { $_.Name -match '^[a-z]+_[a-z]+$' }
z9gpfhce

z9gpfhce2#

让我补充一下Santiago's helpful answer,这是您特定问题的最佳解决方案,并回答您问题标题所暗示的“一般”问题:
我如何测试字符串是否包含给定字符的 * 精确N* 次出现,对于N >= 0?

$char = '_'
$n = 2
@(
  'no underscore',
  'one_underscore',
  'two_underscores_here'
  'three_underscores_are_here'
) | 
  Where-Object {
    # Matches only 'two_underscores_here'
    ($_ -replace "[^$char]").Length -eq $n
  }

注意事项:

*-replace"[^$char]"使用regex实际上删除了除感兴趣的字符之外的所有字符,只留下一个由感兴趣的字符的示例组成的字符串,其长度意味着出现次数。

  • 对于至多N /小于N至少N /大于N逻辑,将-eq替换为-le/-lt-ge/-gt
    可选,直接调用[regex]::Matches().NET API:
$char = '_'
$n = 2
@(
  'no underscore',
  'one_underscore',
  'two_underscores_here'
  'three_underscores_are_here'
) | 
  Where-Object {
    # Matches only 'two_underscores_here'
    ([regex]::Matches($_, "[$char]")).Count -eq $n
  }

为了完整起见:**如果N等于1或N是 * 固定的 ,或者您需要 * 至少-N 个逻辑,并且您不介意更复杂的regexes增加的复杂性,您也可以使用-match**如下所示:

  • 为简单起见,在下面的示例中,感兴趣的字符被 * 硬编码 * 为-
  • 为了更容易适应其他字符,即使对于正匹配,它也包含在[...]中,即使对于_来说这不是严格必要的。
@(
  'no underscore',
  'one_underscore',
  'two_underscores_here'
  'three_underscores_are_here'
) | 
  Where-Object {
    # Matches only 'one_underscore'
    $_ -match '^[^_]*[_][^_]*$'
  }

*固定 * N值> 1的示例;请注意,正则表达式的部分所需的显式重复(通过\1反向引用稍微减轻)使得这对于较大的N值是不切实际的:

# N = 2
@(
  'no underscore',
  'one_underscore',
  'two_underscores_here'
  'three_underscores_are_here'
) | 
  Where-Object {
    # Matches only 'two_underscores_here'
    $_ -match '^[^_]*([_])[^_]*\1[^_]*$'
  }
  • 有关正则表达式的解释和使用它的能力,请参见this regex101.com page
    At-least-N逻辑大大简化了正则表达式:
# N >= 2
@(
  'no underscore',
  'one_underscore',
  'two_underscores_here'
  'three_underscores_are_here'
) | 
  Where-Object {
    # Matches 'two_underscores_here' and 'three_underscores_are_here'
    $_ -match '_.*_'
  }

边缘情况N是0是最容易处理的,因为你只需要确保 no_存在,这很容易用-notmatch来做到:

# N = 0
@(
  'no underscore',
  'one_underscore',
  'two_underscores_here'
  'three_underscores_are_here'
) | 
  Where-Object {
    # Matches only 'no underscore'
    $_ -notmatch '[_]'
  }
8yparm6h

8yparm6h3#

Where-Object {$_.name -match "_.*?_"}将检查输入字符串中是否有2个或更多下划线,但您需要的是相反的。因此,您可以使用NOT运算符反转$_.name -match "_.*?_"的输出:

Where-Object { !($_.name -match "_.*?_") }

相关问题