Windows PowerShell

超酷管道技巧回顾

Don Jones

 

上个月,我向您介绍了一种超酷的管道技巧,该技巧利用管道参数绑定 将较复杂的任务转化为简单的 Windows PowerShell 单行命令。

现在我们简要复习一下:我先创建了一个逗号分隔值 (CSV) 文件,其中包含需要在 Active Directory 域中创建的新用户的相关信息,并确保 CSV 文件的列标题与 New-ADUser cmdlet 的参数名称匹配,该 cmdlet 与 Windows Server 2008 R2 一同提供,还可与 Windows Server 2003 域一起使用。因此列标题是诸如“Department”、“City”、“Name”、“GivenName”、“Surname”等项。由于 New-ADUser 是由属性名称绑定管道输入,所以通过选择这些列名,我只使用两个 cmdlet 即可创建用户:

Import-CSV c:\new-users.csv | New-ADUser

Import-CSV cmdlet 为 CSV 文件的每行输出对象,并且这些对象的某些属性与 CSV 列名相对应。此 CSV 文件包含了 New-ADUser所有所需参数,所以无需手动指定任何参数,不过我可以指定不存在于此文件的任何参数,并且这些参数对于每个新用户(如下例所示的一个组织)是有效的:

Import-CSV c:\new-users.csv | New-ADUser –organization "OurCompany"

我觉得本示例真正强调了 Windows PowerShell 的强大功能:在 VBScript 中,此任务要求使用多行脚本才可实现(在 Windows PowerShell 中,您也可以通过这种方式执行此类任务)。但是,掌握管道的工作原理并在几个编写正确的 cmdlet 的帮助下,此“脚本”将由几个简单的命令取代。

那么,问题在哪里呢?

一些聪颖的读者在我的网站(网址为 www.ConcentratedTech.com)上提出了问题,指出我的超酷技巧仅在 CSV 文件的列名与 New-ADUser 中的参数名称完全 匹配时才适用。如果由管理员创建 CSV 文件,您也许能够获得完全匹配;但如果文件出自人力资源部之手,则列名称更可能是“First Name”、“Last Name”等,而非 New-ADUser 将这些属性自动绑定到其参数所需的完全匹配。

当然,您可以对人力资源部发送给您的任何文件或数据库进行编辑,但如果这种繁琐的工作由自己完成,我们为什么还要发明计算机?所以,Windows PowerShell 提供了一种快速且简单的用于“重命名”属性的方法:Select-Object cmdlet。

Select-Object 是这些 cmdlet 之一,其功能很强大,所以学习使用它可能有些困难。例如,其一项主要任务就是通过消除当时不需要的属性来简化对象。仅指定您一定 要保留的属性,cmdlet 将输出简化的对象。这可使输出显示和文本文件更为清晰一点,例如:

Get-WmiObject Win32_OperatingSystem | Select-Object BuildNumber,ServicePackMajorVersion

还可以使用 Select-Object 选择管道中的部分对象,此时需要借助 –first–last 参数:

Get-Process | Sort VM –desc | Select –first 10

请注意,在以上示例中,我使用的是别名 Select,而不是整个 cmdlet 名称。

解决方案

我们通常会忽视 Select-Object 的另一个功能,即它不仅可以选择您所需的属性,还可以对它们进行重命名。如果您曾阅读过有关该 Help Select –full cmdlet 的完整帮助,我强烈建议您使用每个 cmdlet 执行 Help Select –full,在该帮助中,您可以找到此功能,甚至可找到如何使用该功能的示例。例如:

Import-CSV c:\new-users.csv | Select @{Name="Surname";Expression={$_."Last Name"}}

如果输入 CSV 文件包含“Last Name”列,则该代码会将此列重命名为“Surname”,从而允许输出属性与 New-ADUser 的参数名称匹配。我需要做的就是创建一个散列表,也称为字典关联性数组。在 Windows PowerShell 中,@ 符号是数组运算符;散列表是由键-值对构成的数组。在此例中,键是我要创建的属性的名称,值是要分配给该属性的内容。在散列表的表达式部分,我可以使用 $_ 变量引用当前管道对象,在此示例中,我检索了其“Last Name”属性(该属性名包含空格,所以我必须用引号将其括起来)。

您可根据需要将任意数量的属性提交给 Select-Object

Import-CSV c:\new-users.csv | Select @{Name="Surname";Expression={$_."Last Name"}}, @{Name="GivenName";Expression={$_."First Name"}}

关键是,Select-Object只按照您的要求输出相应内容,因此您不能只要求它重命名一列或两列,而是要求它输出这两列以及您需要重命名的各列。通常,您需要指定要输出到下个 cmdlet 的每个 属性。当然,如果您不需要从 CSV 文件重命名每列,则只能列出以下内容:

Import-CSV c:\new-users.csv | Select @{Name="Surname";Expression={$_."Last Name"}}, @{Name="GivenName";Expression={$_."First Name"}},Department,Organization,Name

在此例中,“Department”、“Organization”和“Name”将在未重命名时传递,这样很好,因为它们可与 New-ADUser 的关联参数完全匹配。

当您要指定许多列时,可能令您感到头痛,因此需要使用以下快捷方法:

Import-CSV c:\new-users.csv | Select @{Name="Surname";Expression={$_."Last Name"}}, @{Name="GivenName";Expression={$_."First Name"}},*

除已创建的“Surname”和“GivenName”属性,“*”还将输出输入对象的所有 属性。因此,假设 CSV 文件如下所示:

First Name,Last Name,Department,Name
Don,Jones,IT,DonJ
Greg,Shields,Janitorial,GregS
Jeff,Hicks,IT,JeffH

然后,我可以使用下列两个 cmdlet:

Import-CSV c:\new-users.csv | Select @{Name="Surname";Expression={$_."Last Name"}}, @{Name="GivenName";Expression={$_."First Name"}},*

每个输出对象都将包含六个 属性:“First Name”、“Last Name”、“Department”、“Name”、“Surname”和“GivenName”。换言之,所有原始属性及我的附加属性。随后,我只需添加 New-ADUser cmdlet:

Import-CSV c:\new-users.csv | Select @{Name="Surname";Expression={$_."Last Name"}}, @{Name="GivenName";Expression={$_."First Name"}},* | New-ADUser

New-ADUser cmdlet 不能使用“First Name”和“Last Name”属性执行任何操作,因为这些属性与其任何参数都不匹配。没关系,cmdlet 会忽略它无法绑定的任何属性。但是,在此例中,它将绑定剩余四个属性:“Surname”、“GivenName”、“Department”和“Name”,并为我创建新用户帐户。

改变您的想法

我发现在使用 Windows PowerShell 时遇到的最大难题之一就是*如何保证永不放弃。*也就是说,如果只是由于列名与所需列名不匹配,而导致您不能使用提供的 CSV 文件,请不要认为更改 CSV 文件就可以解决问题!Windows PowerShell 几乎总是能够满足您的要求,只是需要您进行简单的研究。

当使用 Windows PowerShell 时,您遇到了哪些棘手的问题?欢迎告诉我,我可能会找到答案并发表后续文章!将问题发布到 www.ConcentratedTech.com,我可以在那里立即在线回答,收集您所提供的其他详细信息并可能为 Microsoft TechNet 杂志 发表后续文章。

Don Jones 是美国经验最丰富的 Windows PowerShell 培训师和作家之一。他每周都会在 ConcentratedTech.com 上发表有关 Windows PowerShell 技巧的博客;您也可以在那里联系他或向他请教问题。

相关内容