PowerShell函数在字符串中查找单词

fsi0uk1n  于 5个月前  发布在  Shell
关注(0)|答案(4)|浏览(64)

我正在寻找一种使用PowerShell从字符串中导出单词的方法。我写了一个函数,可以从大写字母开始吐出每个字符的位置:

function Get-WordList {
  [cmdletbinding()]
  param(
    [string]$InputString
  )

  $WordList = $inputString -csplit '\W+|(?<=[a-z0-9])(?=[A-Z])|(?<=[a-z])(?=[A-Z0-9])'

  Return ($WordList | Select-Object -Unique)
}

字符串
我用字符串测试了这个:

Get-WordList -InputString "DeviceManagementGroup"
Get-WordList -InputString "SG-AD-XYZ-8021xAuth"
Get-WordList -InputString "Azure ATP mylab Viewers"
Get-WordList -InputString "SG-AZ-XYZ-MDM-WindowsBYOD-Devices-DYN"
Get-WordList -InputString "SG-AZ-XYZ-Entra-M365E5Licensed-Users"
Get-WordList -InputString "SG-AZ-UserGrp-Microsoft365ServiceAccounts"
Get-WordList -InputString "SG-AZ-UserGrp-AzureServiceAccounts"
Get-WordList -InputString "SG-AZ-DynDeviceGrp-Autopilot-AADJTagged"


这几乎100%的时间工作,除了当它涉及到多个大写字母在一排。在最后一个例子中,有AADJTagged。它认为它是一个词,我绑在分裂它像:

  • Get-WordList -InputString“SG-AZ-DynDeviceGrp-Autopilot-AADJTagged”*
SG
AZ
Dyn
Device
Grp
Autopilot
AADJ
Tagged


相反,它是这样的:

SG
AZ
Dyn
Device
Grp
Autopilot
AADJTagged


我知道我在正则表达式中缺少了一些东西,比如对正则表达式的积极前瞻.有什么想法吗?

e5njpo68

e5njpo681#

试试下面的匹配模式。

(?<!^|[- ])(?=[A-Z][a-z])|[- ]

字符串
输出

SG, AZ, Dyn, Device, Grp, Autopilot, AADJ, Tagged
Device, Management, Group
SG, AD, XYZ, 8021x, Auth
Azure, ATP, mylab, Viewers
SG, AZ, XYZ, MDM, WindowsBYOD, Devices, DYN
SG, AZ, XYZ, Entra, M365E5, Licensed, Users
SG, AZ, User, Grp, Microsoft365, Service, Accounts
SG, AZ, User, Grp, Azure, Service, Accounts
SG, AZ, Dyn, Device, Grp, Autopilot, AADJ, Tagged

yebdmbv4

yebdmbv42#

假设一个“单词”必须以大写字母开头,这与它们匹配:
第一个月
所以它尝试了2场比赛:

  1. 2个或更多连续的大写字母,后面不跟[a-z 0 -9](或大写字母),因为这将是一个新单词的开始。
  2. 1个大写字母,后跟任意数量的[a-z 0 -9]
    你对数字的规则是什么?“-2-",“-A2-",“-2A-",“-2a-",“-a2-".包含单词吗?如果你有任何进一步的规范或更多的测试用例要考虑,请告诉我。
    代码:
function Get-WordList {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory,Position=0)][String] $InputString
    )

    $Pattern = '([A-Z](?![a-z0-9])){2,}|[A-Z][a-z0-9]*'
    $Result = $InputString | Select-String -AllMatches -CaseSensitive -Pattern $Pattern
    Return $Result.Matches.Value | Select -Unique
}

Get-WordList @'
SG-AZ-DynDeviceGrp-Autopilot-AADJTagged
DeviceManagementGroup
SG-AD-XYZ-8021xAuth
Azure ATP mylab Viewers
SG-AZ-XYZ-MDM-WindowsBYOD-Devices-DYN
SG-AZ-XYZ-Entra-M365E5Licensed-Users
SG-AZ-UserGrp-Microsoft365ServiceAccounts
SG-AZ-UserGrp-AzureServiceAccounts
'@

字符串
输出量:

SG
AZ
Dyn
Device
Grp
Autopilot
AADJ
Tagged
Management
Group
AD
XYZ
Auth
Azure
ATP
Viewers
MDM
Windows
BYOD
Devices
DYN
Entra
M365
E5
Licensed
Users
User
Microsoft365
Service
Accounts

k0pti3hp

k0pti3hp3#

这个正则表达式似乎可以做到这一点:

\W+|(?<=[a-z0-9])(?=[A-Z])|(?<=[a-z])(?=[A-Z0-9])|\W+|(?<=\p{Ll})(?=\p{Lu})

字符串
可能有一个更干净的正则表达式,但这是我能说的最好的。

smdnsysy

smdnsysy4#

前言

  • 下面的解决方案基于-csplit(PowerShell的-split-运算符的大小写敏感变体)构建,因此也输出根本不包含小写字母的单词。
  • 通过使用\p{Lu}\p{Ll}(一致地),* 所有 * 和 * 字母都匹配,而不仅仅是 * 英文 *(ASCII范围)字母([A-Z][a-z])。

your own solution的一个更可读和更可维护的替代方案,它利用了inline regex option(?x)IgnorePatternWhitespace),它允许使用附带的空格和#的行尾注解,以获得更好的可读性:

$regex = @'
(?x) # Split by any (|) of the following subexpressions:
  \W+ | # nonempty run of non-word characters such as spaces and "-"
  (?<=\w)(?=\p{Lu}\p{Ll}) |   # *at* UPPER followed by lower, *if preceded by* a word char. (i.e. word-internal)
  (?<=[\p{Ll}\d])(?=\p{Lu}) | # *at* UPPER, *if preceded by* lower or digit
  (?<=\p{Ll})(?=\d)           # *at* digit, *if preceded by* lower
'@

$sampleString = @'
AB-ATP mylab-snakeCase-CamelCase-upperLAST--aclU-AADJTagged
8021xAuth-Microsoft365ServiceAccounts-M365E5
'@

$sampleString -csplit $regex

字符串

  • 这将Get-WordList函数的行为与所需的增强相匹配:将AADJTagged这样的单词拆分为AADJTagged
  • 数字处理没有改变,这意味着M365E5被拆分为M365E5,这是基于推断的规则,即只有数字前面的**字母才能导致数字的拆分。
  • 如果需要的话,调整子表达式和添加新的子表达式应该是很简单的-注意(?x)内联选项必须保持在封闭的逐字here-string字面量的第一行的开头。
  • 有关正则表达式的更详细的解释以及使用它进行实验的**选项,请参阅this regex101.com page
  • 下面的截图显示了所有匹配的分隔符 spans(蓝色)(匹配\W+)和 positions(粉色)(匹配基于 *lookaroundAssert * 的后续子表达式)。
  • x1c 0d1x的数据

PowerShell控制台中的输出:

AB
ATP
mylab
snake
Case
Camel
Case
upper
LAST
acl
U
AADJ
Tagged
8021x
Auth
Microsoft
365
Service
Accounts
M365
E5


[*]表达式(如\p{Lu})用于表示大写字符,是Unicode字符 * 类别 *。请注意,除了大写字母和小写字母之外,还存在其他字母类别,如\p{Lt}用于表示 * 标题大小写 * 字母。

相关问题