2

我在 Powershell 中使用 Select-String 进行了很多正则表达式匹配。

例如,最简单也可能是最常见的匹配,一个 IPv4 地址:

$regex = \b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b

现在,如果我要在一行中匹配这个:

$输出=`

“Blah blah blah,202.100.100.9,你要匹配这行中间的IP,

但不在这一行,因为 '2.a.3.one' 不是有效的 IPv4 地址”

然后我做:

$output | Select-String $regex

它会给我整条线。

我真的不能以原始形式使用它。

但是,如果我使用这个:

$output | Select-String $regex | %{$_.Matches} | %{$_.Value}

它只会给我 IP 地址,这很棒。

我的问题是:

有没有更简单的方法来做到这一点?

我宁愿不打字 | %{$ .Matches} | %{$ .Value} 每次我只想抓取一个特定的字符串。

4

3 回答 3

5

如果您更喜欢 Select-String 而不是 -replace 运算符(这只是调用 [Regex]::Replace 的语法糖),PowerShell V3 有一些快捷方式可以节省一些输入。

首先,Select-String => sls 有一个别名。其次,使用简单的 foreach-object 脚本块,您可以只用属性替换脚本块。

结合这些,您可以使用

$output | sls $regex | % Matches | % Value

为了节省更多的输入,PowerShell 可以制表符完成匹配但不是值。

另一个更少输入的选项是使用属性语法:

($output | sls $regex).Matches.Value

作为奖励,在此示例中,制表符完成可以完成匹配和值。请注意,第二个示例在 V2 中有效,但前提是只有一个匹配行。如果有多个匹配行,只有在 V3 中才能看到所有结果,如果启用严格模式,V2 将不显示任何内容或错误。

于 2013-11-12T15:40:44.887 回答
1

试试这个:

$output -replace ".*($regex).*",'$1'
于 2013-11-12T06:03:32.780 回答
0

首先,我要感谢大家的帮助和努力为我解决这个问题。您的所有建议都很好,而且很有用。

我有一个想法,我意识到我正在寻找一个实际上并不存在的命令,所以我只是为它编写了一个函数:

function Regex-Match {

    [cmdletbinding()]
    param (
        [parameter(Position=0,Mandatory=$true,ValueFromPipeline=$false)]$RegexString,
        [parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true)]$SearchString        
    )

    $Results = @($SearchString | Select-String -Pattern $RegexString | % {$_.Matches} | % {$_.Value})

    Return $Results
}

为了进一步缩短这个,我可以使用

New-Alias -Name regx -Value Regex-match

示例命令:

"test string" | regx "\w\s\w"

或者

Regex-Match -SearchString (gc .\Stuff.txt) -RegexString "\w+"
于 2013-11-13T00:59:36.423 回答