PowerShell正则捕获URL问题:匹配指定格式URL并排除第二个参数
解决PowerShell正则捕获URL的两个问题
咱们一步步拆解你遇到的问题,逐个解决:
问题1:第一个URL为啥没被捕获?
先看你输入文本里的第一个链接:
< a href="http://example.com/Test.aspx?u=a1">
注意<和a之间有个空格,但你的正则写的是<a(没有空格),这直接导致第一个<a>标签根本没被正则匹配到!
把正则开头改成兼容空格的版本就行:
$pattern = '<\s*a href="(http://example.com/Test.aspx\?u=.*?)[&"]'
这里\s*表示匹配0个或多个空白字符,不管标签里有没有空格都能命中。
问题2:捕获组机制的困惑
方法1:为啥拿不到括号里的捕获内容?
你在方法1里遍历的是$group.Captures,但其实[regex]::Matches返回的每个Match对象里,Groups集合才是核心:
Groups[0]:整个正则匹配的完整内容(比如<a href="http://example.com/Test.aspx?u=b2&)Groups[1]:你用括号定义的第一个捕获组,也就是你真正想要的URL
修改方法1的代码,就能拿到目标内容:
Write-Host "----------- Method 1 --------------" $matches = [regex]::Matches($fileContents, $pattern) $matchNum = 0 foreach ($match in $matches) { Write-Host "Match=$matchNum 完整匹配内容=$match" # 直接取第一个捕获组的Value Write-Host "Match=$matchNum 捕获到的URL=$($match.Groups[1].Value)" $matchNum++ }
方法2:为啥输出多余内容?
你写的[regex]::Matches($fileContents, $pattern).Groups.Captures.Value会把所有组的捕获结果都拉出来——包括Groups[0](完整匹配的冗余内容)和Groups[1](目标URL),所以才会出现多余的结果。
要只获取捕获组1的内容,过滤一下就行,修正后的方法2代码:
Write-Host "----------- Method 2 --------------" # 遍历每个Match对象,只提取Groups[1]的Value $urls = [regex]::Matches($fileContents, $pattern) | ForEach-Object { $_.Groups[1].Value } Write-Host "Number of Matches = $($urls.Count)" foreach ($url in $urls) { Write-Host "URL: $url" }
完整可运行的测试代码
把所有修正整合起来,完整代码如下:
$fileContents = 'Misc Text < a href="http://example.com/Test.aspx?u=a1">blah blah</a> More Stuff <a href="http://example.com/Test.aspx?u=b2&parm=123">blah blah </a> Closing Text' # 修正后的正则,兼容<a>标签里的空格 $pattern = '<\s*a href="(http://example.com/Test.aspx\?u=.*?)[&"]' Write-Host "RegEx Pattern=$pattern" Write-Host "----------- Method 1 --------------" $matches = [regex]::Matches($fileContents, $pattern) $matchNum = 0 foreach ($match in $matches) { Write-Host "Match=$matchNum 完整匹配内容=$match" Write-Host "Match=$matchNum 捕获到的URL=$($match.Groups[1].Value)" $matchNum++ } Write-Host "----------- Method 2 --------------" $urls = [regex]::Matches($fileContents, $pattern) | ForEach-Object { $_.Groups[1].Value } Write-Host "Number of Matches = $($urls.Count)" foreach ($url in $urls) { Write-Host "URL: $url" }
运行后就能正确捕获到两个目标URL:
http://example.com/Test.aspx?u=a1http://example.com/Test.aspx?u=b2
内容的提问来源于stack exchange,提问作者NealWalters
相关产品推荐
相关产品推荐

