Windows 10 64-bit. PowerShell 5.1
Parsing local \ remote html with PowerShell 5.1 match regex.
Output everything between the body tags. Do not include / include <body> tags in results. See working on a local / remote file below. See find anything between any <tag> and the very first instance of </tag> below.
Greedy and lazy quantifiers explained
regex101.com is your friend.
Never use (.?|\n), always use (?s).*?
Copy and paste into PowerShell 5.1. It will output everything between <body></body>. The results outputs twice, once without the body tags and once with.
$testhtml = @'
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>AdminWeb</title>
<base href="/wwwroot/admin-web/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<script src="/wwwroot/admin-web/runtime.js"></script><script src="/wwwroot/admin-web/file1.js" nomodule></script>
<script src="/wwwroot/admin-web/file2.js"></script><script src="/wwwroot/admin-web/styles.js"></script>
<script src="/wwwroot/admin-web/vendor.js"></script><script src="/wwwroot/admin-web/main.js"></script>
</body>
</html>
'@
$testhtml -match '(?s)(?<=<body>).*?(?=<\/body>)';$matches[0]
$testhtml -match '(?s)(<body>).*?(<\/body>)';$matches[0]
The command can be written:
[regex]::matches($testhtml,'(?s)(?<=<body>).*?(?=<\/body>)').Value
[regex]::matches($testhtml,'(?s)(<body>).*?(<\/body>)').Value
Three different commands to work on a local file. Output does not include body tags:
(gc -Raw test.html) -match '(?s)(?<=<body>).*?(?=<\/body>)';$matches[0]
[Regex]::Matches((gc -Raw test.html), '(?s)(?<=<body>).*?(?=<\/body>)').Value
gc test.html -Raw | Select-String '(?s)(?<=<body>).*?(?=<\/body>)' -AllMatches | % { $_.Matches } | % { $_.Value }
Output to results.html:
gc test.html -Raw | Select-String '(?s)(?<=<body>).*?(?=<\/body>)' -AllMatches | % { $_.Matches } | % { $_.Value } | sc results.html
Remote url without and with body tag:
$testhtml = Invoke-WebRequest -Uri http://www.pgatour.com
$testhtml -match '(?s)(?<=<body>).*?(?=<\/body>)'
$matches[0]
$testhtml -match '(?s)(<body>).*?(<\/body>)'
$matches[0]
Remote url without and with body tag. Output to results.html:
$testhtml = Invoke-WebRequest -Uri http://www.pgatour.com
$testhtml -match '(?s)(?<=<body>).*?(?=<\/body>)'
$matches[0] | sc results.html
$testhtml -match '(?s)(<body>).*?(<\/body>)'
$matches[0] | sc results.html
Remote url between any tag and the first instance of /tag
$testhtml = Invoke-WebRequest -Uri http://www.pgatour.com
$testhtml -match '(<div class="success-message">)(?s).*?(<\/div>)'
$matches[0]
Invoke-WebRequest -Uri http://www.pgatour.com | sc results.html
(gc -raw results.html) -match '(<div class="success-message">)(?s).*?(<\/div>)'
$matches[0]
Remote url by classname. These work but are not very productive. See Parsing HTML Webpages with Powershell
$response = Invoke-WebRequest -Uri http://www.pgatour.com
$response.ParsedHtml.body.getElementsByClassName('success-message')
$( $response.ParsedHtml.getElementsByTagName('div') | ?{$_.className -eq 'success-message'} ).outerHTML
$( $response.ParsedHtml.body.getElementsByTagName('div') | Where {$_.getAttributeNode('class').Value -eq 'success-message'} ).outerHTML