PowerShell从字符串中解析名称和版本

时间:2018-08-10 18:33:36

标签: regex powershell

我想解析字符串的名称和版本。

字符串的架构如下:

EntityFramework.6.2.0

EntityFramework.Functions.1.4.1

我想要的是一个带有包名称和版本的数组或对象。

版本号可以包含1,2,3或4位数字,名称也可以包含“。”。

$version = @()
$name = @()

"EntityFramework.Functions.1.4.1".Split('.') | % {
  if ($_ -match "^\d+$"){
   $version += $_
  }else{
    $name += $_
  }
}

$name -join "."
$version -join "."

这行得通,但我认为有更好的方法。

任何缩短此摘要或使其更聪明的主意。

3 个答案:

答案 0 :(得分:3)

这可以从一开始就依靠正则表达式来改善:

$null = 'EntityFramework.Functions.1.4.1' -match '(?<name>[^\d]+)(?<version>\d.+)'
$name, $version = $Matches['name'].TrimEnd('.'), [version]$Matches['version']

$name
>> EntityFramework.Functions

$version
>> Major  Minor  Build  Revision
>> -----  -----  -----  --------
>> 1      4      1      -1

解释:

(           // Capture a group  
  ?<name>   // Name it "name"
    [^\d]+  // Capture until you find a digit
)           // End capture group

(             // Capture a group
  ?<version>  // Name it "version"
    \d.+      // Start at a digit and wildcard catch everything after
)             // End capture group

缩短(适用于haxxorz)

if ('EntityFramework.Functions.1.4.1' -match '(.*?(?=\.\d))\.(.+)')
{
    $name, [version]$version = $matches[1, 2]
}

(gottagoshort):

$name,$version='EntityFramework.Functions.1.4.1'-split'(?<=[^\d])\.(?=\d)'

答案 1 :(得分:2)

注意:这是下面原始答案的优化变体,由TheIncorrigible1提供。

通过使用 -split运算符使用环视断言 的分隔符正则表达式,可以在其中拆分字符串一次操作即可找到所需的位置:

# Stores 'EntityFramework.Functions' in $name
# and '1.4.1' in $version
$name, $version = "EntityFramework.Functions.1.4.1" -split '(?<=[^\d])\.(?=\d)'
  • (?<=[^\d])\.(?=\d)使用一个在后面的表情断言((?<=...)和一个在前面的表情 断言((?=...))为匹配文字.\.)提供所需的上下文:

    • 仅当不是数字(.且是< em>后跟一个数字,这是我们要分割的位置:包名称的末尾和版本号的开头。

    • Regex断言通常不会捕获字符,因此,即使看着周围的字符,也只有[^\d]被视为分隔符,以确保其两侧的令牌都已全部归还。

  • .操作的结果是一个2元素数组,可以通过解构分配(-split)将其元素分配给单个变量


原始答案

注意:尽管下面使用的正则表达式比上面的正则表达式短一些,但是它与$name, $version = ...的相互作用实际上在概念上更复杂,因此该解决方案需要执行其他操作才能滤除空的结果元素({{1 }}。

使用-split运算符和正则表达式(正则表达式)的更简洁的解决方案:

-ne ''
  • -split在字符串(# Stores 'EntityFramework.Functions' in $name # and '1.4.1' in $version $name, $version = "EntityFramework.Functions.1.4.1" -split '^([^\d]+)\.' -ne '' )的开头开始匹配,然后匹配一个或多个(^([^\d]+)\.)个非数字字符(^)由文字+[^\d]

    • 这与.匹配,但是由于仅将{em}之前的部分{em> 封闭在\.中以形成捕获组,返回EntityFramework.Functions.
      (默认情况下,分隔符正则表达式匹配的是 not 返回的-毕竟,您只希望分隔符之间 的标记-而是捕获组内嵌在正则表达式中的代码可用于在结果数组中故意包含部分分隔符。

    • 根据定义,在输入字符串中再也找不到分隔符正则表达式(因为它是用.锚定在字符串的开头的,因此字符串的其余部分-(...)-被视为第二个也是唯一的令牌。

  • EntityFramework.Functions过滤掉结果数组中空的第一个元素,该元素是字符串以分隔符正则表达式的匹配项开头的副作用。

    • 在典型情况下,您的正则表达式仅匹配分隔符,而不在结果数组中包括它们(或其中的一部分);因此,除非输入真正以分隔符实例开头或您有相邻的分隔符,否则您将不会获得空元素;例如,^产生1.4.1,没有空元素。

答案 2 :(得分:0)

@(
'EntityFramework.6.2.0',
'EntityFramework.Functions.1.4.1'
) | %{

    [pscustomobject]@{
        name = $_ -replace '\.([0-9]).*([0-9])$'
        version = $_ -replace '^([A-Za-z]).*([A-Za-z])\.'
    }
}

这根据一组字符类型将每个项目分开。