用于两个特殊字符之间的字符串的Powershell正则表达式

时间:2019-02-08 03:50:50

标签: regex powershell

文件名如下

$inpFiledev = "abc_XYZ.bak"

我只需要一个变量中的XYZ即可与其他文件名进行比较。 我在下面尝试过:

[String]$findev = [regex]::match($inpFiledev ,'_*.').Value
Write-Host $findev

4 个答案:

答案 0 :(得分:5)

正则表达式中的星号的行为与在文件系统列表命令中的行为不同。就目前而言,您的正则表达式正在寻找下划线,重复零次或多次,后跟任意字符(在正则表达式中以句点表示)。因此,正则表达式会在字符串开头立即找到零个下划线,然后找到“ a”,这就是它返回的匹配项。

首先,更正该位:

'_*.'

成为“下划线,后跟任意数量的字符,后跟文字句号”。 “文学时期”表示我们需要使用\.来跳过正则表达式中的时期,记住该时期意味着任何字符:

'_.*\.'
  • _下划线
  • .*任意数量的字符
  • \.文字期间

返回:

_XYZ。

所以,距离不远。

如果您希望从字符之间返回某些内容,则需要使用捕获组。在要保留的位上加上括号:

'_(.*)\.'

然后,您将需要使用PowerShell正则表达式组来获取值:

[regex]::match($inpFiledev ,'_(.*)\.').Groups[1].Value

哪个返回:XYZ

Groups [1]中的数字1表示第一个捕获组,可以通过使用更多的括号将任意数量的表达式添加到表达式中,但是在这种情况下,您只需要一个即可。

答案 1 :(得分:4)

用两个PowerShell惯用的替代方法补充mjsqu's helpful answer

有关在PowerShell中如何使用 regexes (正则表达式)的概述,请参见Get-Help about_regular_expressions


使用-split除以_.,提取所得的3元素数组的中间元素:

PS> ("abc_XYZ.bak" -split '[_.]')[1]
XYZ
  • -split的(第一个)RHS操作数是一个正则表达式;正则表达式[_.]是与单个字符相匹配的字符集[...])。 _因此,输入.被分成一个包含字符串abc_XYZ.bakabcXYZ的数组。因此,应用索引bak会提取中间令牌[1]

使用XYZ通过捕获组(-replace,在替换操作数中称为(...))提取感兴趣的令牌:

$1
  • PS> "abc_XYZ.bak" -replace '^.+_([^.]+).+$', '$1' XYZ 也在正则表达式上作为第一个RHS操作数-要替换的内容-而第二个操作数指定了将匹配的(sub)字符串替换的内容。 / p>

  • 正则表达式-replace

    • ^.+_([^.]+).+$在输入(^.+_的开头匹配一个或多个(+)字符(.)-注意{{1} }-在字符集(^之外使用-是一个正则表达式元字符,它表示任何字符(在单行输入字符串中)。

    • .是一个捕获组[...]),与取反的字符集(([^.]+))相匹配: (...)匹配任何文字字符。 不是文字[^...]一次或多次([^.])。

    • 无论.中与子表达式匹配的内容,都可以在替换操作数中引用为+,其中(...)表示捕获组中基于1的索引。正则表达式在这种情况下,$<n>可以用于引用此第一个(也是唯一一个)捕获组。

    • <n>匹配一个或多个($1)个剩余字符(.+$),直到到达输入结尾(+)。

  • 替换操作数.仅指第一个捕获组所匹配的内容。在这种情况下:$

    • 有关$1替换操作数的语法的全面概述,请参见this answer

答案 2 :(得分:1)

由于您使用的是[regex]加速器,因此需要反斜杠来结束.的结尾(如果要匹配它),并且在星号之前需要一个点以匹配任何字符下划线之后。如果两者之间的字符都是字母,请使用\w+

$findev = [regex]::match($inpFiledev ,'_.*\.')
$findev
_XYZ.

答案 3 :(得分:1)

这演示了另外两种从样本字符串中获取所需信息的方法。第一种在原始字符串上使用基本的Object.equals()字符串方法。第二个假设是您要处理文件对象,首先从获取文件的.Split()开始。已经删除了扩展名,因此您不必费心去做。

如果您要处理的是个字符串,而不是文件对象,那么以前的正则表达式答案可能会更快。 [咧嘴]

.BaseName

输出...

$inpFiledev = 'abc_XYZ.bak'
$findev = $inpFiledev.Split('.')[0].Split('_')[-1]

# fake reading in a file with Get-Item or Get-ChildItem
$File = [System.IO.FileInfo]'c:\temp\testing\abc_XYZ.bak'
$WantedPart = $File.BaseName.Split('_')[-1]

'split on a string         = {0}' -f $findev
'split on BaseName of file = {0}' -f $WantedPart