如何使用 PowerShell 提取子字符串?
我有这个字符串...
"-----start-------Hello World------end-------"
我必须提取...
Hello World
最好的方法是什么?
-match
运算符测试正则表达式,将其与神奇变量$matches
结合起来以获得结果
PS C:\> $x = "----start----Hello World----end----"
PS C:\> $x -match "----start----(?<content>.*)----end----"
True
PS C:\> $matches['content']
Hello World
每当对正则表达式有疑问时,请查看此网站:http://www.regular-expressions.info
Substring
方法为我们提供了一种根据起始位置和长度从原始字符串中提取特定字符串的方法。如果仅提供一个参数,则将其视为起始位置,并输出字符串的其余部分。
PS > "test_string".Substring(0,4)
Test
PS > "test_string".Substring(4)
_stringPS >
但这更容易...
$s = 'Hello World is in here Hello World!'
$p = 'Hello World'
$s -match $p
最后,递归浏览目录,仅选择 .txt 文件并搜索“Hello World”的出现:
dir -rec -filter *.txt | Select-String 'Hello World'
不确定这是否有效,但可以使用数组索引语法引用 PowerShell 中的字符串,与 Python 类似。
这不是完全直观,因为第一个字母是由
index = 0
引用的,但它确实:
以下是一些示例:
PS > 'Hello World'[0..2]
产生结果(为了清楚起见,包含索引值 - 不在输出中生成):
H [0]
e [1]
l [2]
通过传递
-join ''
可以使其更有用:
PS > 'Hello World'[0..2] -join ''
Hel
使用不同的索引可以获得一些有趣的效果:
转发
使用小于第二个索引值的第一个索引值,子字符串将按照您的预期向前提取。这次第二个索引值远远超出了字符串长度但没有错误:
PS > 'Hello World'[3..300] -join ''
lo World
不同于:
PS > 'Hello World'.Substring(3,300)
Exception calling "Substring" with "2" argument(s): "Index and length must refer to a location within
the string.
向后
如果您提供的第二个索引值低于第一个索引值,则以相反的方式返回字符串:
PS > 'Hello World'[4..0] -join ''
olleH
从结束
如果使用负数,则可以引用从字符串末尾开始的位置。要提取最后 5 个字母
'World'
,我们使用:
PS > 'Hello World'[-5..-1] -join ''
World
PS> $a = "-----start-------Hello World------end-------" PS> $a.substring(17, 11) or PS> $a.Substring($a.IndexOf('H'), 11)
$a.Substring(argument1, argument2)
--> 这里 argument1
= 所需字母表的起始位置,argument2
= 您想要作为输出的子字符串的长度。
这里 17 是字母表的索引
'H'
因为我们想要打印直到 Hello World,所以我们提供 11 作为第二个参数
以马特的答案为基础,这是一个跨换行符搜索的答案,并且很容易修改以供您自己使用
$String="----start----`nHello World`n----end----"
$SearchStart="----start----`n" #Will not be included in results
$SearchEnd="`n----end----" #Will not be included in results
$String -match "(?s)$SearchStart(?<content>.*)$SearchEnd"
$result=$matches['content']
$result
--
注意:如果您想对文件运行此命令,请记住 Get-Content 返回一个数组而不是单个字符串。 您可以通过执行以下操作来解决此问题:
$String=[string]::join("`n", (Get-Content $Filename))
其他解决方案
$template="-----start-------{Value:This is a test 123}------end-------"
$text="-----start-------Hello World------end-------"
$text | ConvertFrom-String -TemplateContent $template
由于字符串并不复杂,因此不需要添加RegEx字符串。简单的搭配就能达到目的
$line = "----start----Hello World----end----"
$line -match "Hello World"
$matches[0]
Hello World
$result = $matches[0]
$result
Hello World
通常直接使用 [regex] 会更容易:
这是
-match
和 $matches
的替代方案,基于 Matt 的答案
PS> $x = "----start----Hello World----end----"
PS> $pattern = "^-*start-*(.*?)-*end-*$"
PS> $found = [regex]::Matches($x,$pattern)
PS> $found
Groups : {0, 1}
Success : True
Name : 0
Captures : {0}
Index : 0
Length : 44
Value : -----start-------Hello World------end-------
PS> $found.Groups
Groups : {0, 1}
Success : True
Name : 0
Captures : {0}
Index : 0
Length : 44
Value : -----start-------Hello World------end-------
Success : True
Name : 1
Captures : {1}
Index : 17
Length : 11
Value : Hello World
PS> $found.Groups[1].Value
Hello World
这允许我们在字符串中找到多个匹配结果,但我们实际上并不需要分组在这里提供的功能,因此look-behind&look-ahead断言将允许我们在不捕获组的情况下进行匹配:
PS> $x = "----start----Hello World----end----"
PS> $pattern = "(?<=-*start-*)[\w\s]*?(?=-*end-*)"
PS> [regex]::Match($x,$pattern).Value
Hello World
PowerShell 和 .NET 正则表达式与普通正则表达式略有不同,因此请务必参考快速参考指南以获取其他快捷方式。
我需要在日志文件中提取几行,这篇文章有助于解决我的问题,所以我想在这里添加它。如果有人需要提取多行,您可以使用脚本获取与该字符串匹配的单词的索引(我正在搜索“Root”)并提取所有行中的内容。
$File_content = Get-Content "Path of the text file"
$result = @()
foreach ($val in $File_content){
$Index_No = $val.IndexOf("Root")
$result += $val.substring($Index_No)
}
$result | Select-Object -Unique
干杯..!
试试这个:
$mystring="------start---Hello World--end---------"
$result=@([regex]::split($mystring,'\-+'))[2]
$result