想要使用 powershell 循环创建逻辑

Want to create a logic using powershell loops

我有一个 .csv 文件,其中包含整个共享邮箱的邮箱委派权限。文件将包含两列,其中提到了电子邮件地址。 IE。谁对什么邮箱有权限。

例如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

Batch1、2、3 等批次中的命名基于下面解释的逻辑。

查看上面的示例 User1、2、3 可以访问 S1,因此它将成为 Batch1。

User1 再次可以访问 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"}

我很无聊,很好奇我该如何处理,所以我继续模拟了你的文件(并添加了一些内容以确保我可以将连续的组放入同一批次中,只要有任何连接的用户):

$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 的键和 User1User2User3 的值。 ColA 中的每个唯一值都有一个类似的项目。

一旦我有了邮箱,并且可以访问这些邮箱的用户被组织和分组,我就继续尝试对它们进行批处理。我从第 1 批开始,所以我为此设置了一个变量。

$i=1

接下来我遍历每个 $Box(即哈希表中的每个键)。这是我将称之为邮箱循环的外循环。

ForEach($Box in $AccessTo.Keys){

在邮箱循环中,我有一个内部循环遍历与该邮箱关联的每个 $User。我将其称为用户循环。

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

再次使用示例数据,第一个邮箱是 S1,与之关联的用户是 User1User2User3。因此,在内部循环中,我首先检查当前用户是否已经分配了一个批次。如果他们这样做,我 continue 给下一个用户。

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

然后我查看哈希表中的每个项目,如果当前 $User 在任何给定邮箱的用户列表中,我将输出该邮箱的所有用户。它通过管道传输到 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 的当前值。我指定 "the current value" 是因为我们在循环内向 $BatchUsers 添加内容。

对于循环的每次迭代,我们再次查看 $AccessTo 哈希表中的所有项目

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

我们检查 $BatchUsers 中的第 $x 项是否在哈希表的该项中。

            ?{$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

就是这样。如果您有具体问题,请随时提出。