Хотите создать логику, используя петли powershell - PullRequest
0 голосов
/ 24 апреля 2018

У меня есть файл .csv, где он содержит разрешения на делегирование почтовых ящиков для всех общих почтовых ящиков.Файл будет содержать две колонки с указанными адресами электронной почты.Т.е. у кого есть разрешения на какие почтовые ящики.

Например, ColA = общие почтовые ящики и ColB = почтовые ящики пользователей.

ColA.  --- ColB
S1        --- User1
S1        --- User2
S1        --- User3
S2        --- User1
S2        --- User4
S3        --- User3
User1  --- S3
S4        --- User5
S4        --- User6
S5        --- User5
User6  --- S5

Требуется присвоить им имена в пакетах, создав еще один столбец.

Например,

ColA      --- ColB. ---ColC
S1        --- User1 ---Batch1
S1        --- User2 ---Batch1
S1        --- User3 ---Batch1
S2        --- User1 ---Batch1
S2        --- User4 ---Batch1
S3        --- User3 ---Batch1
User1     --- S3    ---Batch1
S4        --- User5 ---Batch3
S4        --- User6 ---Batch3
S5        --- User5 ---Batch3
User6     --- S5    ---Batch3

Именование в пакетах, таких как Пакет1, 2,3 и т. Д., Основано на логике, описанной ниже.

Глядя выше, например, Пользователь1,2,3 имеют доступ к S1, поэтому это будет Batch1.

Пользователь1 снова имеет доступ к S2, поэтому он перейдет в Batch1, поскольку он уже существовал в Batch1.

User4 имеет доступ к S2, поэтому онбудет идти в Batch1, потому что S2 ранее существовал в Batch1

Таким же образом все остальные пользователи имеют доступ к почтовым ящикам и должны быть пакетированы путем создания вышеуказанной логики.

Я пытался написать код с помощьюиспользуя циклы и сохраняя их в переменную, а затем используя объект сравнения.Но это не помогает мне.

Я написал наполовину код, как я понимаю ниже.

$csv = import-csv c:\permlist.csv 
$compare = compare-object $csv.colA 
$csv.ColB -includeequal Foreach ($x in $compare.name) if 
($compare.sideindicator -eq "=>") 
{write-output "Exist in column B"} else {write-output "exist in column A"}

1 Ответ

0 голосов
/ 25 апреля 2018

Мне было скучно, и мне было любопытно, как я справлюсь с этим, поэтому я продолжил и смоделировал ваш файл (и добавил немного к нему, чтобы быть уверенным, что я получу последовательные группы в одном пакете, пока естьлюбые подключенные пользователи):

$FileIn = @'
ColA,ColB
S1,User1
S1,User2
S1,User3
S2,User1
S2,User4
S3,User3
User1,S3
S4,User5
S4,User6
S5,User5
User6,S5
S6,User4
S6,User7
S7,User7
S7,User8
'@ -split '[\r\n]+'|convertfrom-csv

Затем выяснил, как отсортировать его по пакетам, убедившись, что я зациклился достаточно, чтобы подключить любую подключенную группу пользователей к одному пакету.

$AccessTo = @{}
$FileIn|Group ColA|%{$AccessTo.add($_.Name,$_.Group.ColB)}

$i=1
ForEach($Box in $AccessTo.Keys){
    ForEach($User in $AccessTo[$Box]){
        If(($FileIn.ColB|?{$_ -eq $User}|Select -First 1).Batch){Continue}
        $BatchUsers = $AccessTo.Keys|?{$AccessTo[$_] -contains $User -or $_ -eq $User}|%{$AccessTo[$_]}|Select -Unique
        Do{For($x=0;$x -lt $BatchUsers.Count;$x++){$AccessTo.Keys|?{$AccessTo[$_] -contains $BatchUsers[$x]}|%{$AccessTo[$_]}|?{$_ -notin $BatchUsers}|%{$BatchUsers+=$_}}}Until($x -eq $BatchUsers.count)
        $FileIn | ?{$_.ColB -in $BatchUsers -and !$_.Batch}|%{Add-Member -InputObject $_ -NotePropertyName 'Batch' -NotePropertyValue $i}
    }
    $i=($FileIn.batch|sort|select -last 1)+1
}

В конце я получаю:

PS C:\Users\TMTech> $FileIn

ColA  ColB  Batch
----  ----  -----
S1    User1     1
S1    User2     1
S1    User3     1
S2    User1     1
S2    User4     1
S3    User3     1
User1 S3        1
S4    User5     2
S4    User6     2
S5    User5     2
User6 S5        2
S6    User4     1
S6    User7     1
S7    User7     1
S7    User8     1

Редактировать: Хорошо, была запрошена разбивка кода, так что поехали.Обратите внимание, что я использую некоторые псевдонимы, в основном: ?{...} - это сокращение от Where{...}, а %{...} - это сокращение ForEach-Object{...}.

Я начинаю с того, что получаю данные в PowerShell и сохраняю их впеременная с именем $FileIn.Вы будете импортировать CSV, поэтому я просто буду двигаться дальше.Затем я создаю пустую хеш-таблицу.

$AccessTo = @{}

Затем я беру импортированные данные, группирую их по значению в ColA и для каждой группировки добавляю элемент в хеш-таблицу, где значение в ColAявляется ключом, а значение является массивом строк из ColB.Например, первый элемент в хеш-таблице имеет ключ S1 и значение User1, User2, User3.Подобный элемент существует для каждого уникального значения в ColA.

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

$i=1

Далее я перебираю каждый $Box (т.е. каждый ключ в хеш-таблице).Это внешний цикл, который я назову циклом почтового ящика.

ForEach($Box in $AccessTo.Keys){

В цикле почтового ящика у меня есть внутренний цикл, который проходит через каждый $User, связанный с этим почтовым ящиком.Я назову это пользовательским циклом.

    ForEach($User in $AccessTo[$Box]){

При повторном использовании данных примера первый почтовый ящик - S1, а связанные с ним пользователи - User1, User2 и User3.Поэтому во внутреннем цикле я начинаю с проверки, назначен ли ему текущий пользователь.Если они это сделают, я continue для следующего пользователя.

        If(($FileIn.ColB|?{$_ -eq $User}|Select -First 1).Batch){Continue}

Затем я смотрю на каждый элемент в хеш-таблице, и если текущий $User находится в списке пользователей для любого данного почтового ящика IВывести всех пользователей для этого почтового ящика.Это передается в команду Select, которая получает только уникальные значения и записывается в $BatchUsers.

        $BatchUsers = $AccessTo.Keys|?{$AccessTo[$_] -contains $User -or $_ -eq $User}|%{$AccessTo[$_]}|Select -Unique

На данный момент у нас есть хорошая база пользователей, которые входят в пакет.Теперь мне просто нужно убедиться, что эти пользователи не входят в другие группы, в которые не входит текущий $User, и если они есть, мне нужно итерировать пользователей из этих дополнительных групп, и я должен продолжать делать этопока я не перестану получать больше пользователей.Я разберем это с форматированием, которое немного легче читать:

Do{
    For($x=0;$x -lt $BatchUsers.Count;$x++){
        $AccessTo.Keys|
            ?{$AccessTo[$_] -contains $BatchUsers[$x]}|
            %{$AccessTo[$_]}|
            ?{$_ -notin $BatchUsers}|
            %{$BatchUsers+=$_}
    }
}Until($x -eq $BatchUsers.count)

Я начинаю с цикла Do / Until, который будет работать сам до тех пор, пока $BatchUsers.Count не будет равно числу пользователей, которыемы рассмотрели последнюю итерацию цикла (поэтому она циклическая, пока не найдет дополнительных пользователей).Внутри этого цикла я запускаю цикл For, который начинается с $x=0 и продолжается до тех пор, пока $x не станет равным текущему значению $BatchUsers.Count.Я указываю «текущее значение», потому что мы добавляем вещи в $BatchUsers внутри цикла.

Для каждой итерации цикла мы снова смотрим на все элементы в хеш-таблице $AccessTo

    For($x=0;$x -lt $BatchUsers.Count;$x++){
        $AccessTo.Keys|

Мы проверяем, находится ли $x-й элемент в $BatchUsers вэтот элемент хеш-таблицы.

            ?{$AccessTo[$_] -contains $BatchUsers[$x]}|

Если это так, мы расширяем всех пользователей в этом элементе хеш-таблицы.

            %{$AccessTo[$_]}|

Затем отфильтровываем тех, которые уже есть в $BatchUsers.

            ?{$_ -notin $BatchUsers}|

Для каждого, которого нет в $BatchUsers, мы добавляем его в $BatchUsers.

            %{$BatchUsers+=$_}

После завершения цикла Do / Untilв поисках пользователей перейдем к нашим исходным данным, спрятанным в $FileInМы повторяем это, просматривая каждую запись, чтобы увидеть, находится ли значение в ColB в $BatchUsers, и проверяем, что ей еще не назначен пакет.

        $FileIn | ?{$_.ColB -in $BatchUsers -and !$_.Batch}

Мы передаем эти записи в цикл ForEach-Object, и для каждой из них добавляем свойство с именем Batch со значением $i (которое мы использовали для отслеживания текущего пакета)

        $FileIn | ?{$_.ColB -in $BatchUsers -and !$_.Batch}|%{Add-Member -InputObject $_ -NotePropertyName 'Batch' -NotePropertyValue $i}

Теперь, когда у каждого в текущем пакете есть значение Пакета, мы устанавливаем $i на единицу больше, чем самый высокий номер партии.Первоначально я просто повторял $i, чтобы быть еще одним для каждого цикла цикла почтовых ящиков, но в один пакет входило несколько ящиков, поэтому я получил пакет 1 и пакет 4, что не имеет большого смысламне.Итак, да, установите следующую партию на единицу выше, чем последняя:

    $i=($FileIn.batch|sort|select -last 1)+1

Вот и все.Если у вас есть конкретные вопросы, пожалуйста, не стесняйтесь спрашивать.

...