Регулярные выражения Powershell, чтобы соответствовать числу без других чисел вокруг - PullRequest
0 голосов
/ 25 января 2019

В библиотеке Sharepoint у нас есть настраиваемое поле, которое является многопользовательским полем, библиотека хранит изображения сотрудников. Однако иногда люди покидают компанию, и нам нужно удалить их фотографии.

Я создал один скрипт, который выполняет следующие шаги:

  1. Выполняет запрос ко всей библиотеке, к многопользовательскому полю, а затем получает уникальный список.
  2. Для каждого пользователя он будет запрашивать список, чтобы увидеть, в каких конкретных элементах списка есть изображение кого-то, кто здесь больше не работает.

Проблема в том, что Sharepoint хранит поле для нескольких человек, например:

57;#JohnSmith 56;#Johanna Smith

Итак, я делаю сравнение с матчем, но не получаю желаемых результатов.

Пример результатов:

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

Первый результат в порядке.

Второй результат, однако, выглядит следующим образом:

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

1 Ответ

0 голосов
/ 29 января 2019

Я мог бы пойти с другим подходом, который разделяет вашу многопользовательскую строку. Это проблема в вашем примере, потому что пользователи разделяются пробелами, но также могут содержать пробелы. Поэтому мы должны объединить его с предсказуемым шаблоном в начале строки, чтобы получить регулярное выражение, которое мы можем использовать для его разделения.

Я изменил вашу примерную строку ввода для тестирования:

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

Мы можем использовать этот шаблон регулярного выражения для разбиения строки: \s(?=\d+;#)

Если вы посмотрите на эту ссылку и нажмете «Разделить список», вы увидите следующее:

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

Что делает RegEx?

  • \s - соответствует пробелу (вы можете заменить его литералом, если хотите, или пробелом \)
  • (?=...) - просмотр с нулевой шириной означает, что все, что здесь есть, должно следовать, но не считается частью матча
  • \d+;# - \d+ означает одну или несколько цифр, ;# - литералы (# необходимо экранировать только в режиме регулярных выражений, где вы можете добавлять комментарии)

Таким образом, в общем, этот шаблон означает: «соответствовать пробелу, но только если за ним следуют 1 или более цифр, затем точка с запятой, затем хеш / фунт / октоторп (#).

Зачем это делать?

Поскольку оператор -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 хранит многопользовательское поле в виде одной строки, где несколько записей разделены пробелами и сами записи могут содержать пробелы. Может быть, вы уже можете получить его в виде массива? Может быть, вы можете получить идентификацию в одиночку и сделать какое-то прямое сравнение? Поиграйте с объектами и опциями, которые у вас есть для запросов к SharePoint, и посмотрите, есть ли что-то, что вы могли бы сделать более простым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...