【问题标题】:Want to create a logic using powershell loops想要使用 powershell 循环创建逻辑
【发布时间】:2018-04-24 19:18:00
【问题描述】:

我有一个 .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"}

【问题讨论】:

  • “我尝试通过使用循环并将它们存储到变量中然后使用比较对象来编写代码。但这对我没有帮助。” - 请发布您的尝试(即使不成功)
  • 您的列表示看起来有点混乱,---for 是什么?
  • 为此道歉。这是我的代码 $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 "存在于 B 列"} else {write-output "存在于 A 列"}
  • @LotPings 可以忽略。它只是格式化。我真的不知道如何在发布时发布和格式化表格。这个社区的新手......;)
  • edit您的问题包含您的代码。

标签: powershell exchange-server-2010


【解决方案1】:

我很无聊,很好奇我会如何处理这个问题,所以我继续模拟了你的文件(并在其中添加了一些内容,以确保只要有任何连接的用户):

$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。例如,哈希表中的第一项的 Key 为 S1,Value 为 User1,User2,User3。 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 等于我们在循环的最后一次迭代中查看的用户数(所以它会循环直到找不到其他用户) .在该循环中,我运行一个从$x=0 开始的For 循环,并循环直到$x 等于$BatchUsers.Count 的当前值。我指定“当前值”是因为我们在循环内向$BatchUsers 添加了一些东西。

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

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

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

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

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

【讨论】:

  • 优秀的伙伴。真是个好主意。非常感谢这一点。如果我在这里要求解释适用于每一行代码的逻辑,可以吗?我只想了解每一行。这对我真的很有帮助。提前致谢。
  • 是的,我可以为你分解它。不过会有点,似乎只是因为他们付钱给我,他们就认为我应该在这里工作。一旦我得到一点停机时间,我会分解它来解释它。
  • 向你致敬,伙计。非常感谢你。很好解释。真是硕果累累。我的大脑开始工作。 ;) 赞成..
猜你喜欢
  • 1970-01-01
  • 2020-10-29
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多