当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] PowerShell 和 Regex:综合指南

作者:精品下载站 日期:2024-12-14 13:03:56 浏览:14 分类:玩电脑

PowerShell 和 Regex:综合指南


理解正则表达式 (regex) 对于我们人类来说可能是一件痛苦的事情,但正则表达式可能是一种处理字符串的非常强大的方式。在本文中,您将学习使用 PowerShell 和 Regex 的基础知识。

您将了解 Select-String 等方便的 cmdlet,了解正则表达式捕获组并了解各种正则表达式解析技术。

先决条件

  • 运行 PowerShell 5.1+ 的 Windows 7 或更高版本计算机。本文将使用 PowerShell 7.1.0。

使用 Select-String 匹配简单文本

要一起演示 PowerShell 和正则表达式,最好通过一个实际示例进行演示。

假设您正在从旧机器收集有关其硬件的数据,并使用 wmic 实用程序构建一个如下所示的简单文本文件。我们将其命名为computername.txt

BiosCharacteristics={7,11,12,15,16,19,20,21,22,23,24,25,27,30,32,33,39,40,42,43}
 BIOSVersion={"ACRSYS - 2","V1.15","INSYDE Corp. - 59040115"}
 BuildNumber=
 Caption=V1.15
 CodeSet=
 CurrentLanguage=
 Description=V1.15
 EmbeddedControllerMajorVersion=1
 EmbeddedControllerMinorVersion=15
 IdentificationCode=
 InstallableLanguages=
 InstallDate=
 LanguageEdition=
 ListOfLanguages=
 Manufacturer=Insyde Corp.
 Name=V1.15
 OtherTargetOS=
 PrimaryBIOS=TRUE
 ReleaseDate=20200826000000.000000+000
 SerialNumber=NXHHYSA4241943017724S00
 SMBIOSBIOSVersion=V1.15
 SMBIOSMajorVersion=3
 SMBIOSMinorVersion=2
 SMBIOSPresent=TRUE
 SoftwareElementID=V1.15
 SoftwareElementState=3
 Status=OK
 SystemBiosMajorVersion=1
 SystemBiosMinorVersion=15
 TargetOperatingSystem=0
 Version=ACRSYS - 2

在本例中,假设您需要提取该计算机的序列号。此序列号位于 SerialNumber= 行。

在这种情况下,Select-String 将成为您最喜欢的新工具。

Select-String 是一个 PowerShell cmdlet,允许您提供正则表达式模式并返回与该模式匹配的字符串。

相关:如何使用 PowerShell 的 Grep(选择字符串)

由于您要查找的模式位于文件中,因此您首先需要读取该文件,然后查找正则表达式匹配。为此,请使用 Pattern 参数提供正则表达式模式,并使用 Path 参数提供文本文件的路径。

Select-String -Pattern "SerialNumber" -Path '.\computername.txt'

Select-String cmdlet 读取 .\computername.txt 文件,尝试查找与 SerialNumber 匹配的一组字符。

[玩转系统] PowerShell 和 Regex:综合指南

不管你相信与否,你已经在使用正则表达式了。正则表达式最简单的形式是匹配特定字符。在这种情况下,您将匹配文字“SerialNumber”短语。

然而,您很可能不想要整行。让我们开始构建一个本机脚本来仅检索您关心的数据。

Select-String 输出是一个丰富的对象

在前面的示例中,Select-String 返回的内容看起来是一个简单的字符串,但实际上输出的内容要多得多。 Select-String 不仅仅输出文本匹配。该 cmdlet 实际上返回整个对象。

例如,指定 This (is) 的正则表达式模式来在字符串 This is a string 中进行搜索。您可以在下面看到,如果将该输出通过管道传递给 Get-MemberSelect-String 将返回一个 Microsoft.PowerShell.Commands.MatchInfo 对象。

select-string "This (is)" -inputobject "This is a String" | get-member

[玩转系统] PowerShell 和 Regex:综合指南

使用捕获组

在前面的示例中,请注意使用的正则表达式模式 (This (is))。该模式包含一组括号。在正则表达式中,这些括号创建一个捕获组。

通过用括号括住搜索词,PowerShell 正在创建一个捕获组。捕获组将正则表达式搜索的内容“捕获”到变量中。

请注意,在上面的示例中,Select-String 输出一个名为 Matches 的属性。此属性包含找到的捕获组(如果使用括号)的所有行或值。

所有捕获组的值都可以在 Matches.Groups 属性下找到。 groups 属性是一个对象数组,其中 value 属性是实际数据。 groups 数组从 0 开始(具有整个正则表达式匹配的值),并按您在正则表达式术语中指定的每个捕获组递增。

对于上面的示例,您可以使用 matches 属性提取整个字符串,以及提取的 is 匹配项:

$match = select-string "This (is)" -inputobject "This is a String"
#this property will match the whole select-string value
$match.Matches.groups[0].value
#this property will match the first capture group
$match.Matches.groups[1].value

[玩转系统] PowerShell 和 Regex:综合指南

将捕获组与模式匹配结合使用

捕获文字字符串与捕获 This is 中的文字 is 毫无意义。您不会通过捕获您已经知道其内容的字符串来获得有价值的数据。您还可以将捕获组与模式匹配结合起来,以仅提取您关心的信息。

模式匹配是使用特殊定义的字符来匹配一定范围的字符,而不是特定的字符。您可以将模式匹配视为类固醇的通配符 * (就像在记事本中一样)。

假设您只想匹配 SerialNumber=NXHHYSA4241943017724S00 行中的序列号,而不是整行。您想要捕获 SerialNumber= 短语之后的任何字符。您可以使用特殊的点 . 字符,后跟正则表达式通配符 *(称为量词)来提取该模式。

点告诉正则表达式匹配 SerialNumber= 之后的任何单个字符。 * 告诉正则表达式重复 . 匹配零次或多次。与捕获组结合使用,正则表达式将类似于 SerialNumber=(.*)。您可以在下面看到这一点:

$string = "SerialNumber=numberwecareabout1042"
#extract the serial number using a capture group
$match = select-string "SerialNumber=(.*)" -inputobject $string
#output the serial number
$match.matches.groups[1].value

[玩转系统] PowerShell 和 Regex:综合指南

特殊的 . 字符只是许多不同的模式匹配可能性之一。您可以匹配单词、字符范围、数字范围等。 regexr 网站上的正则表达式参考类别(通过侧边栏)是不同正则表达式的绝佳资源。

实用的 PowerShell 正则表达式示例

将以上所有内容放在一起,让我们创建一个脚本:

  1. 提取文本文件列表(在示例中,您将仅获取示例文本文件)
  2. 循环遍历文本文件,并使用 SerialNumber=(.*) 查找序列号
  3. 生成一个哈希表,其中包含计算机名称及其关联序列号的列表
#Create a hashtable to hold the serial numbers
$serialNumbers = @{}

#Get all of the text files. In this case, you are limiting your scope to a single text file
$files = Get-ChildItem "$pwd\computername.txt"

#populate the hashtable
foreach ($file in $files) {
    #first, retrieve that same string, like in the first example. This time, also capture the information after the label in a capture group
    $serialNumber = select-string "SerialNumber=(.*)" $file.FullName
    #now, use the capture group to extract the serial number only. This is done using the special matches property. We also use the filename (without extension) as the index for the serial number
    $serialNumbers[$file.basename] = $serialNumber.matches.groups[1].value
}
# write the output of the hashtable to the screen
$serialNumbers | format-table

您可以使用 computername.txt 查看上述脚本的运行情况:

[玩转系统] PowerShell 和 Regex:综合指南

Match 运算符

您已经学习了如何使用 Select-String 来匹配文本中的正则表达式模式,但 PowerShell 也有一些支持正则表达式的方便运算符。

最有用和最流行的 PowerShell 正则表达式运算符之一是 matchnotmatch 运算符。这些运算符允许您测试字符串是否包含特定的正则表达式模式。

如果字符串确实与模式匹配,则match运算符将返回True值。如果不是,它将返回 False 值。对于 notmatch 运算符来说,情况正好相反。

下面您将看到此行为的一个简单示例。

#example of using a match parameter
if("my string" -match "string") {
    "string is in my string!"
}

Split 运算符

如果您想按空格、逗号或制表符等非静态字符拆分字符串,可以使用 split 运算符。 split 运算符对字符串执行正则表达式匹配,并执行第二个操作:将字符串拆分为一个或多个字符串。

split 运算符将字符串“转换”为按特定正则表达式模式拆分的字符串数组。

#create an array of strings split by the "\" symbol. The "\" is escaped within split because it is a special character
"somebody\once told me\the world\is going\to roll me" -split ("\")

ValidatePattern 参数验证

PowerShell 的正则表达式支持不仅仅限于 cmdlet 和运算符;您还可以在参数中集成正则表达式匹配。

相关:您想了解的有关 PowerShell 参数的一切

使用 ValidatePattern 参数验证属性,您可以根据正则表达式模式验证字符串参数值。此验证例程对于限制用户可用于参数值的输入很有用。

#example validation using regex. The ValidatePattern in this function will
#only accept lowercase or uppercase alphabetical letters, as well as spaces.
#the ^ at the start of the regex represents the start of the string, and $ at the end
#represents the end of the string (to match the *entire* string). The +
#means that the string must have one or more characters to be accepted
function alphaOnly {
    param([ValidatePattern('^[a-zA-Z ]+$')][string]$alphaCharacters)
    write-output $alphaCharacters
}
#this will succeed
alphaOnly "Hi Mom"
#this will fail
alphaOnly "Hi Mom!"

使用 PowerShell 和 Regex 替换文本

在前面的部分中,您学习了使用 PowerShell 和正则表达式匹配模式的几种不同方法。您可以进一步利用这一知识,并替换 PowerShell 匹配的文本。

用正则表达式替换文本的一种流行方法是使用 -replace 运算符。 -replace 运算符采用两个参数(用逗号分隔),并允许您使用正则表达式将字符串替换为替换项。 -replace 还支持捕获组,允许您在搜索中匹配捕获组并在替换中使用匹配项。

例如,使用 -replace 您可以将文本附加到序列号:

$string = "SerialNumber=numberwecareabout1042"
$currentYear = "2020"
#append the year to the end of the serialnumber
$serialNumber = $string -replace "SerialNumber=(.*)","SerialNumber=`$1-$currentYear"
write-output $serialNumber

[玩转系统] PowerShell 和 Regex:综合指南

请注意,在上面的示例中,$1 中的美元符号是使用反引号转义的。否则,PowerShell 会将 $1 视为变量而不是特殊的正则表达式字符。

学习如何编写更好的 PowerShell 正则表达式

上述所有内容可能听起来很复杂,而且确实如此。事实上,上面的示例中没有涵盖许多正则表达式功能。幸运的是,正则表达式是一种广泛使用的机器阅读方法,并且有大量实用程序可以帮助学习如何有效地使用正则表达式。

  • RegexOne 被认为是学习正则表达式的事实上的资源。 Regexone 以简短且交互式的方式介绍了正则表达式的功能,让您在编写正则表达式时学习它。 RegexOne 是一个很棒的资源,可以让您从头开始学习正则表达式的工作原理
  • Regexr 是验证和构建正则表达式的最佳工具之一。除了拥有出色的实时正则表达式测试工具之外,regexr 还包括一个备忘单和一个出色的文档引擎。
  • Regexstorm 特别使用 .Net 引擎来驱动其工具。该网站没有 Regexr 等网站所具有的所有功能,但它像 PowerShell 一样准确地测试您的正则表达式。即使您使用其他工具来构建正则表达式,您也应该始终通过 regexstorm 运行正则表达式,以确保 PowerShell 能够正确解析它。

如果没有必要,请勿使用 PowerShell 和 Regex!

PowerShell 围绕对象工作。 PowerShell 是围绕结构化对象构建的。具有属性的对象比正则表达式发挥作用的松散文本更容易管理。

相关:回归基础:了解 PowerShell 对象

PowerShell 以及 JSON 等结构化语言的主要目的之一是淘汰正则表达式和文本解析。人类语言非常适合正则表达式的破译,但一般来说,在存储或传输数据时,您会尽量避免使用正则表达式。

相关:使用 PowerShell 和 JSON 处理 REST API

有些人甚至因为在结构化语言上使用正则表达式而兴奋

如果您可以使用面向对象的方法或结构化语言(例如 JSON、XML 等)而不是正则表达式,那就去做吧!尽管您可以使用正则表达式做任何事情,但这并不意味着您应该这样做!

继续使用正则表达式

通过本文,您现在应该对正则表达式如何帮助机器解析和查找文本有基本的了解,即使是在查找高度具体或复杂的短语时也是如此。您还应该拥有在 PowerShell 上下文中测试、验证和了解正则表达式的工具。

如果您还没有这样做,RegexOne 教程是一个很棒的下一步。测试您的正则表达式知识并增强您在 PowerShell 中的字符串能力!

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯