在PowerShell中选择字符串(grep)时,如何仅返回匹配的正则表达式?

Sky*_*ler 41 regex powershell grep

我试图在文件中找到一个模式.当我得到一场比赛时,Select-String我不想要整条线,我只想要匹配的部分.

有没有我可以用来做这个的参数?

例如:

如果我做了

select-string .-.-.
Run Code Online (Sandbox Code Playgroud)

并且该文件包含一行:

abc 1-2-3 abc
Run Code Online (Sandbox Code Playgroud)

我想得到的结果只有1-2-3,而不是返回整行.

我想知道Powershell相当于一个 grep -o

Kei*_*ill 38

要不就:

Select-String .-.-. .\test.txt -All | Select Matches
Run Code Online (Sandbox Code Playgroud)

  • `回声“abcd”| 选择字符串-模式 '(ab)' | 选择匹配`返回{0} (12认同)
  • 添加一些附加信息:“ Select [-Object] Matches”输出_custom objects_具有从.Select-String的“ [Microsoft.PowerShell.Commands.MatchInfo]”类型的输出对象中复制的.Matches属性。如果要输出正则表达式捕获的实际_text_,请使用`ForEach-Object {$ _。Matches [0] .Value}`,假设每行只有1个匹配项。如果有多个(可能是由于-All [Matches]`导致的,则相当于grep -o`),可以在PSv3 +中使用“ ForEach-Object {$ _。Matches.Value}”;在PSv2中,您必须显式枚举`$ _。Matches`集合。 (3认同)
  • 和 `ForEach-Object { $_.Matches.Value }` 每场比赛返回一个空行... (2认同)

Ste*_*ski 26

大卫正走在正确的道路上.[regex]是System.Text.RegularExpressions.Regex的类型加速器

[regex]$regex = '.-.-.'
$regex.Matches('abc 1-2-3 abc') | foreach-object {$_.Value}
$regex.Matches('abc 1-2-3 abc 4-5-6') | foreach-object {$_.Value}
Run Code Online (Sandbox Code Playgroud)

如果它太冗长,你可以将它包装在一个函数中.


ste*_*tej 22

我尝试了其他方法:Select-String返回属性可以使用的匹配.要获得所有匹配项,您必须指定-AllMatches.否则它只返回第一个.

我的测试文件内容:

test test1 alk atest2 asdflkj alj test3 test
test test3 test4
test2
Run Code Online (Sandbox Code Playgroud)

剧本:

select-string -Path c:\temp\select-string1.txt -Pattern 'test\d' -AllMatches | % { $_.Matches } | % { $_.Value }
Run Code Online (Sandbox Code Playgroud)

回报

test1 #from line 1
test2 #from line 1
test3 #from line 1
test3 #from line 2
test4 #from line 2
test2 #from line 3
Run Code Online (Sandbox Code Playgroud)

在technet.microsoft.com上选择字符串


Car*_*lsh 12

您可以使用更简单的成员枚举%语法,而不是通过管道传输,它可以神奇地作用于多个元素:select.prop

(Select-String .-.-. .\test.txt -All).Matches.Value
Run Code Online (Sandbox Code Playgroud)

或更少的括号:

$m = Select-String .-.-. .\test.txt -All
$m.Matches.Value
Run Code Online (Sandbox Code Playgroud)


Jay*_*kul 11

本着教人钓鱼的精神......

您要做的是将select-string命令的输出传递给Get-member,这样您就可以看到对象具有哪些属性.一旦你这样做,你会看到"匹配",你可以通过管道输出来选择它| **Select-Object** Matches.

我的建议是使用类似的东西:select linenumber,filename,matches

例如:在stej的样本上:

sls .\test.txt -patt 'test\d' -All |select lineNumber,fileName,matches |ft -auto

LineNumber Filename Matches
---------- -------- -------
         1 test.txt {test1, test2, test3}
         2 test.txt {test3, test4}
         3 test.txt {test2}
Run Code Online (Sandbox Code Playgroud)


小智 8

以上答案都不适合我。下面做到了。

Get-Content -Path $pathToFile | Select-String -Pattern "'test\d'" | foreach {$_.Matches.Value}

Get-Content -Path $pathToFile | # Get-Content will divide into single lines for us

Select-String -Pattern "'test\d'" | # Define the Regex
Run Code Online (Sandbox Code Playgroud)

foreach {$_.Matches.Value} # 只返回对象的匹配字段的值。(这允许多个结果匹配。)


小智 7

如果不想使用ForEach运算符,则只能使用管道和Select -Expand

例如,要仅获取 后的路径C:\,您可以使用:

Get-ChildItem | Select-String -Pattern "(C:\\)(.*)" | Select -Expand Matches | Select -Expand Groups | Where Name -eq 2 | Select -Expand Value
Run Code Online (Sandbox Code Playgroud)

Where Name -eq 2仅选择指定正则表达式模式的第二个匹配项。