Regex для получения текста между двумя текстами с помощью командной строки - PullRequest
3 голосов
/ 06 марта 2020

Я пытаюсь извлечь содержимое из тега body в моем файле html, используя командную строку и команду findstr. Мой html такой, как показано ниже

<!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>

Я хочу получить следующий результат:

<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>

Я пытаюсь добиться с помощью регулярного выражения.

findstr /R (?<=<body>)(.*)(?=</body>)  test.html

Но теперь это работает в командной строке. Но это регулярное выражение работает в js.

Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 06 марта 2020

Прежде всего, findstr не поддерживает все классные функции регулярных выражений, которые предлагают современные движки регулярных выражений. Особенно новейшие JavaScript ECMAScript2018 + совместимые двигатели, такие как Chrome, Node.js, et c. Таким образом, утверждение « это регулярное выражение работает в js» не означает, что тот же шаблон будет работать в другом месте. Конечно, это не сработает в findstr.

. Вы можете пойти трудным путем и go изучить, как написать пакетный скрипт для этого. Тем не менее, есть гораздо более простой способ с другими встроенными Windows приложениями.

Я настоятельно рекомендую Powershell, поскольку он предлагает вам множество функций. NET предоставляет.

Здесь откройте PowerShell консоль и используйте

$pathToFile = 'c:\...\...\you_file.txt'
$output_file = 'c:\...\...\you_file_out.txt' 
$rx = '(?s)(?<=<body>).*?(?=</body>)'
Get-Content $pathToFile -Raw | Select-String $rx -AllMatches | % { $_.Matches } | % { $_.Value } > $output_file

ПРИМЕЧАНИЕ : для обработки HTML.

$output_file = 'c:\...\...\you_file_out.txt'
$url = 'http://your_site_here.tld/...'
$ie = New-Object -comobject "InternetExplorer.Application"
$ie.visible = $true
$ie.navigate($url)

while ($ie.Busy -eq $true -Or $ie.ReadyState -ne 4) {Start-Sleep 2}

$doc = $ie.Document
$tags = $doc.getElementsByTagName("body")
$tags[0].innerHTML > $output_file
лучше всего использовать IE.
2 голосов
/ 06 марта 2020

Windows 10 64-бит. PowerShell 5.1

Разбор локального \ удаленного html с помощью регулярного выражения PowerShell 5.1.

Вывести все между тегами тела. Не включайте / включайте <body> теги в результаты. Смотрите работу с локальным / удаленным файлом ниже. См. Найти что-нибудь между любым <tag> и самым первым экземпляром </tag> ниже.

Объясненные жадные и ленивые квантификаторы

regex101.com ваш друг.

Никогда не используйте (. ? | \ n) , всегда используйте (? s). *?

Скопируйте и вставьте в PowerShell 5.1. Он выведет все между <body></body>. Результаты выводятся дважды, один раз без тегов body и один раз с.

$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] 

Команда может быть записана:

[regex]::matches($testhtml,'(?s)(?<=<body>).*?(?=<\/body>)').Value
[regex]::matches($testhtml,'(?s)(<body>).*?(<\/body>)').Value

Три разные команды для работы с локальным файлом. Вывод не включает теги тела:

(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 }

Вывод результатов. html:

gc test.html -Raw | Select-String '(?s)(?<=<body>).*?(?=<\/body>)' -AllMatches | % { $_.Matches } | % { $_.Value } | sc results.html 

Удаленный URL-адрес без и с тегом тела:

$testhtml = Invoke-WebRequest -Uri http://www.pgatour.com
$testhtml -match '(?s)(?<=<body>).*?(?=<\/body>)'
$matches[0]
$testhtml -match '(?s)(<body>).*?(<\/body>)'
$matches[0]

Удаленный URL-адрес без и с тегом тела. Вывод результатов. 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

Удаленный URL-адрес между любым тегом и первым экземпляром / 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] 

Удаленный URL-адрес по имени класса. Они работают, но не очень продуктивно. См. Синтаксический анализ HTML Веб-страниц с 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 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...