我想构建一个PowerShell脚本,该脚本在字符串中第一次出现给定字符后返回该短语。例如,我想在v
字符首次出现后得到所有短语:
blah_v1.2
foo_v1
vbarv_2.4
bar
结果将是
1.2
1
barv_2.4
我试图构建类似这样的东西,但是$ FooVersion返回一个布尔值而不是一个字符串。
$Foo = "blah_v1.1"
$FooVersion = $Foo -match "_v (.*)"
Write-Host $Foo
Write-Host $FooVersion
有什么想法吗?干杯
答案 0 :(得分:3)
尝试一些可能性:
<rule ref="SlevomatCodingStandard.TypeHints.TypeHintDeclaration">
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint"/>
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.enableEachParameterAndReturnInspection"/>
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.normalizedTraversableTypeHints"/>
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.normalizedUsefulAnnotations"/>
</rule>
或
$Foo = "blah_v1.1"
# using -replace
# returns a string without 'v' as-is
$FooVersion = $Foo -replace '(?:[^v]*v)(.*)', '$1'
或
# using -split at the first 'v' character
# returns a string without 'v' as-is; use [1] to return '' instead
$FooVersion = ($Foo -split 'v', 2)[-1]
答案 1 :(得分:1)
确保先查找不是v
的所有内容,然后是第一个v,然后从$Matches
变量中获取捕获的值:
$strings = -split @'
blah_v1.2
foo_v1
vbarv_2.4
bar
'@
$strings |ForEach-Object {
if($_ -match '[^v]*v(.*)'){
$Matches[1]
}
}
答案 2 :(得分:1)
将-replace
operator与输入字符串数组结合使用可提供一种简洁的解决方案:
# Sample input lines (string array)
$lines = @'
blah_v1.2
foo_v1
vbarv_2.4
bar
'@ -split '\r?\n'
# Perform a regex-based string replacement on each input line,
# so as to only extract the substrings of interest.
$lines -replace '.*?v(.*)', '$1'
以上结果:
1.2
1
barv_2.4
bar
给定一个 array 作为LHS,-replace
一一对应于数组的元素。
正则表达式.*?v(.*)
非贪婪地(?
)匹配任何内容(.*
)直到 first v
,然后(贪婪地)捕获捕获组(v
中(...)
之后的任何内容,替换操作数中的$1
都指向该捕获组,并且由于正则表达式与整个输入字符串匹配,所以输出就是在输入的第一个v
之后。
请注意, -replace
会按原样传递与正则表达式不匹配的输入,这就是为什么bar
不包含{{1}的原因},也出现在输出中;如果您想 省略行而没有v
,如示例输出中所示:
v
请注意@($lines) -match 'v' -replace '.*?v(.*)', '$1'
周围的@(...)
,这可以确保LHS始终被视为 array ,因为$lines
仅充当具有数组的过滤器,值LHS,而不是单个输入字符串(请参见下文)。
(根据定义,以上示例输入是一个数组,但是例如,如果您使用-match
从文件中加载行,则单行输入文件将产生单字符串,不在1元素数组中。)
Get-Content
返回包含字母-match 'v'
的{{1}}元素的子数组,$line
然后对其进行运算。
注意:
数组+ v
方法对于已经在内存中的集合非常方便快捷。
ForEach-Object
-based answer。也就是说,如果您知道输入集可以放入整个内存中,则可以通过捕获表达式(-replace
中的管道(cmdlet)输出,或者通过保证数组来提高性能。 ,-replace
),(...)
可以再次应用于:
@(...)
关于您尝试过的事情:
使用标量 LHS,-replace
返回一个布尔值(指示输入是否匹配),如您所见。
但是,使用标量 LHS(仅用于!),PowerShell会在自动@(Get-Content input.txt) -replace '.*?v(.*)', '$1'
哈希表中填充有关匹配的匹配项((sub)字符串(条目{{1} }),捕获组值(第一个捕获组的条目-match
,...),因此您可以使用此后的 ,如Mathias' answer所示。 / p>