【问题标题】:Powershell regular expressions to match a number with no other numbers aroundPowershell正则表达式匹配一个没有其他数字的数字
【发布时间】:2019-01-29 10:44:29
【问题描述】:

在 Sharepoint 库中,我们有一个自定义字段,它是多用户字段,该库存储员工图片。但是有时人们离开公司,我们需要删除他们的照片。

我创建了一个执行以下步骤的脚本:

  1. 它对整个库、多用户字段进行查询,然后得到一个唯一列表。
  2. 然后,它会针对每个用户查询列表,以查看哪些特定列表项有一张不再在这里工作的人的照片。

Sharepoint 存储多人字段的问题如下:

57;#JohnSmith 56;#Johanna Smith

所以,我所做的是与匹配项进行比较,但我没有得到我想要的结果。

示例结果:

56;#John Smith
Picture1_2012_09_07_123jpg.jpg +  + 56;#John Smith

第一个结果是OK的。

第二个结果是这样的:

WilliamGates_1jpg.jpg +  + 056;#William Gates (Not OK)
JeanClaudeVanDamme_2011_05_24__112jpg.jpg +  + 560;#JeanClaudeVanDamme (Not OK)

我的脚本:

Add-PSSnapin Microsoft.Sharepoint.powershell

#$ErrorActionPreference = "Stop"
#Set-StrictMode -Version "Latest"

#. .\Functions-Logging.ps1

#Start-History -name "PDB Asset Cleaning"

$site = Get-SPSite https://oursharepointsite.com/sites/pdb/
$web = $site.RootWeb

$expiredAccountFound = $false

$context = Get-SPServiceContext $site
$profileManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)

$camlQuery = New-Object Microsoft.SharePoint.SPQuery
$camlQuery.Query = '<Where><And><Neq><FieldRef Name="ContentType" /><Value Type="Computed">Folder</Value></Neq><IsNotNull><FieldRef Name="Persons_PDB" /></IsNotNull></And></Where>'
$camlQuery.ViewFields = '<FieldRef Name="Persons_PDB" />'
$camlQuery.ViewFieldsOnly = $true
$camlQuery.ViewAttributes = 'Scope="Recursive"'

$list = $web.Lists.TryGetList("Assets")

$listItems = $list.GetItems($camlQuery)

$filteredItems = $listItems | ForEach-Object {$_.Item("Persons_PDB").LookupValue} | Select -Unique

$date = Get-Date

$fileName = "D:\Installers\PictureDB\R 1.0\Scripts\Add-ArtifactsToWeb\" + $date.ToShortDateString().Replace('/','-') + ".txt"

$message = "Report of " + $date.ToShortDateString() 
$message += "`r`n"
$message += "`r`n"

foreach($item in $filteredItems)
{
    $user = $web.EnsureUser($item)
    if (-Not $profileManager.UserExists($user.LoginName))
    {
        $loginName = $user.LoginName.Substring(13)
        Write-Host $loginName
        $userFromAD = Get-ADUser -Filter {SAMAccountName -eq $loginName}
        $concatenatedUser = $user.ID.ToString() + ";#" + $userFromAd.Name
        Write-Host  $concatenatedUser
        $query = [String]::Format("<Where><Contains><FieldRef Name='Persons_PDB' LookupId='True'/><Value Type='LookupMulti'>{0}</Value></Contains></Where>",$user.ID)
        $userItemsQuery = New-Object Microsoft.SharePoint.SPQuery
        $userItemsQuery.Query = $query
        $userItemsQuery.ViewAttributes = 'Scope="Recursive"'
        $userItems = $list.GetItems($userItemsQuery)

        foreach($item in $userItems)
        {
           if($item["Persons_PDB"].ToString() -match $concatenatedUser)
           {
                write-host $item.File.Name +" " + $item["Persons_PDB"]

           } 

             #Write-Host $item . "will be deleted"
            #Write-Host $list.GetItemById($item.Id)
            #$list.GetItemById($item.Id).Recycle()
        }
    }
}





$web.Dispose()
$site.Dispose()

#Stop-History

【问题讨论】:

  • -match 期望 $concatenatedUser 是正则表达式,但您没有提供正则表达式。它是否适用于简单的“-eq”?字符串中的 # 可能会造成混淆,因为它具有特殊含义(注释):Regular Expression Quick Reference
  • 你可以试试-match [Regex]::Escape($concatenatedUser)

标签: regex powershell sharepoint


【解决方案1】:

我可能会采用不同的方法,即拆分您的多用户字符串。这在您的示例中很痛苦,因为用户由空格分隔,但也可以包含空格。所以我们必须将它与字符串开头的可预测模式结合起来,得到一个可以用来分割它的正则表达式。

我将您的示例输入字符串修改为以下内容以进行测试:

57;#JohnSmith 56;#Johanna Smith 59;#Alexander Graham Bell 060;#Persona Non Grata

We can use this regex pattern to split the string: \s(?=\d+;#)

如果您查看该链接并单击拆分列表,您会看到:

  1. 57;#JohnSmith
  2. 56;#Johanna Smith
  3. 59;#Alexander Graham Bell
  4. 060;#Persona Non Grata

RegEx 的作用是什么?

  • \s - 匹配空格(如果需要,您可以将其替换为文字空格,或转义空格 \
  • (?=...) - 零宽度前瞻,意味着这里的任何内容都必须遵循,但不计入匹配项
  • \d+;# - \d+ 表示一个或多个数字,;# 是文字(# 只需要在可以包含 cmets 的正则表达式模式下进行转义)

因此,总而言之,此模式的意思是:“匹配一个空格,但前提是它后跟 1 个或多个数字,然后是分号,然后是哈希/磅/octothorpe (#)。

为什么要这样做?

因为-split 运算符可以将正则表达式作为何时将字符串拆分为数组的基础。

为什么要使用数组?

因为您只需检查您要查找的单个用户是否在 数组中:

foreach($item in $userItems)
{
   $persons = $item["Persons_PDB"].ToString() -split '\s(?=\d+;#)'
   if($concatenatedUser -in $persons) # or $persons -contains $concatenateduser
   {
        write-host $item.File.Name +" " + $item["Persons_PDB"]
   } 
}

你所做的一切有必要吗?

我不知道。如果无法访问对象,则很难分辨。但在我看来,SharePoint 不太可能将多用户字段存储作为单个字符串,其中多个条目由空格分隔并且条目本身可以包含空格。也许您已经可以将其作为数组获取?也许您可以单独获取ID并进行某种直接比较?试玩一下用于查询 SharePoint 的对象和选项,看看是否有更简单的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 2021-03-05
    • 1970-01-01
    • 2015-03-05
    • 2014-09-17
    • 1970-01-01
    • 2019-07-05
    相关资源
    最近更新 更多