Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Select-String. Парсинг нескольких значений между наборами символов. (http://forum.oszone.net/showthread.php?t=345862)

rango13 17-07-2020 18:44 2928481

Select-String. Парсинг нескольких значений между наборами символов.
 
Всем привет!
Уже второй день бьюсь с задачей: есть текстовый файл, из которого необходимо вывести на экран несколько слов/цифр, находящихся между определённым текстом.

Кусок файла, пример

...
!--PREVINFO_START-->Autodesk AutoCAD Electrical 2015<!--PREVINFO_END--></dfsdferwer
'word-break:break-all'>УH5S SV65 V9У1 WDL3 </td></tr>erwedfsdf
td align=left id=2>21T81</td><td align=leftwerewrwer
...
!--PREVINFO_START-->Autodesk AutoCAD 2018<!--PREVINFO_END--></dfsdferwer
'word-break:break-all'>YWP8 10NT JHGJ NJJZ </td></tr>erwedfsdf
td align=left id=2>T2281</td><td align=leftwerewrwer

Такого рода записей может быть несколько из-за нескольких установленных версий Автокада.


После работы скрипта результат должен быть таким

Autodesk AutoCAD Electrical 2015
УH5S SV65 V9У1 WDL3
21T81

Autodesk AutoCAD 2018
YWP8 10NT JHGJ NJJZ
T2281


Первую строку достаю командой:
Код:

(Select-String "(?<=!--PREVINFO_START--&gt;)(.*?)(?=]&lt;!--PREVINFO_END--&gt;&lt;/)" -InputObject $content -AllMatches | foreach {$_.matches}).value
Но при этом парсится сразу две первые строчки названий программы. Но не могу понять, как задать сразу несколько условий в запросе выше, чтобы парсилось и название, и серийник, и код продукта. Можете подтолкнуть в правильном направлении?

Fors1k 17-07-2020 20:10 2928483

Код:

param(
    $path = "C:\files\qwe.txt"
)cls

(gc $path|sls '(?<=&gt;).+?(?=&lt)' -all).Matches.Value


rango13 18-07-2020 02:05 2928509

Цитата:

Цитата Fors1k
param(
Код:

$path = "C:\files\qwe.txt"
)cls
(gc $path|sls '(?<=&gt;).+?(?=&lt)' -all).Matches.Value »


Извините, я привёл только кусок текста. В полном варианте много где встречается набор символов, начинающихся с "&gt;" и заканчивающихся на "&lt". В итоге в выводе получается много лишней информации.

Пример

&lt;!--PREVINFO_START--&gt;Autodesk AutoCAD Electrical 2015
&lt;/td&gt;
&lt;td align=left id=1&gt;&amp;nbsp;
&lt;td align=left id=2&gt;&amp;nbsp;
&lt;td align=left id=1 width=15%&gt;Серийный номер:
&lt;td align=left id=2&gt;
&lt;!--PREVINFO_START--&gt;421-64324142
&lt;/td&gt;
&lt;td align=left id=1 width=15%&gt;Ключ продукта:
&lt;td align=left id=2&gt;21T81
&lt;td align=left id=1&gt;&amp;nbsp;
&lt;td align=left id=2&gt;&amp;nbsp;
&lt;td align=left id=1 width=15%&gt;Код запроса:


Скажите, можно ли в той конструкции, которую вы написали, использовать несколько условий, т.е. обычными словами:

Найти все вхождения в файле, располагающиеся между набором символов ("!--PREVINFO_START--&gt;" и "]&lt;!--PREVINFO_END--&gt;&lt;/") ИЛИ ("'word-break:break-all'&gt;" и "&lt;/td&gt;&lt;/tr&gt;erwedfsdf") ИЛИ ("td align=left id=2&gt;" и "&lt;/td&gt;&lt;td align=leftwerewrwer") ?

DJ Mogarych 18-07-2020 11:43 2928523

Код:

(gc C:\temp\test\text.txt) -replace "^.*?gt;" -replace "&lt;.*?$"

Sham 18-07-2020 12:26 2928528

Регулярное выражение на всю группу строк с подмасками. Выводим подмаски.
Код:

$regexp = "!--PREVINFO_START--&gt;(.*?)&lt;!--PREVINFO_END--&gt;&lt;/dfsdferwer
'word-break:break-all'&gt;(.*?)&lt;/td&gt;&lt;/tr&gt;erwedfsdf
td align=left id=2&gt;(.*?)&lt;/td&gt;"

Select-String $regexp -InputObject $content -AllMatches |
        % {$_.Matches | % {$_.Groups[1..3].Captures.Value; "`n"}}


Fors1k 18-07-2020 15:54 2928548

Цитата:

Цитата rango13
Скажите, можно ли в той конструкции, которую вы написали, использовать несколько условий »

Код:

param(
    $path = "C:\files\qwe.txt"
)cls

$name  = "(?<=PREVINFO_START--&gt;).*(?=&lt;!--PREVINFO_END)"
$serial = "(?<=word-break:break-all'&gt;).*(?=&lt;/td&gt)"
$code  = "(?<=align\=left id\=2&gt;).*(?=&lt;/td)"

(gc $path|sls "$name|$serial|$code" -all).Matches.Value


YuS_2 18-07-2020 19:32 2928569

Цитата:

Цитата rango13
Уже второй день бьюсь с задачей »

Задача разовая или периодическая, которая требует автоматизации? Лучше от этого отталкиваться...
Цитата:

Цитата rango13
Можете подтолкнуть в правильном направлении? »

Если говорить о правильном направлении, то лучше декодировать текст, чтобы получить валидный html текст и его уже парсить на предмет необходимых тегов таблицы.
Код:

gc test.txt -enc utf8|%{[net.webutility]::htmldecode($_)}
и далее, либо воспользоваться встроенным парсером html, либо (что лучше и будет работать, в том числе и в версиях powershell core) воспользоваться внешним модулем PowerHTML
Код:

#---Эту секцию можно удалить после однократного запуска скрипта от имени админа ------------------
# Установка дополнительного модуля PowerHTML, для независимого парсинга HTML
# Может потребоваться ручное подтверждение установки.
if (!(get-module -list powerhtml)) {
        write-verbose "Installing PowerHTML module for the current user..."
        install-module powerhtml #-scope currentuser
}
#-----------------------------------------------------------------------------------------


ivan.vas 15-10-2021 15:11 2968893

Цитата:

Цитата Fors1k
(gc $path|sls "$name|$serial|$code" -all).Matches.Value »

Подскажите, при такой конструкции получается вывод следующий будет?
Код:

$name
$serial
$code

Есть ли возможность вывода в одну строку, к примеру вот так:
Код:

$name $serial $code
$name $serial $code
$name $serial $code
$name $serial $code
$name $serial $code
$name $serial $code


alpap 15-10-2021 16:08 2968903

чтобы так выводить надо преобразовывать под определенный формат, для примера чтобы было понятно что я имею ввиду:
Код:

$hash = [Ordered]@{
  'name'  = 'a', 'b', 'c'
  'serial' = 1, 2, 3
  'code'  = 'i', 'j', 'k'
}

foreach ($i in $hash.GetEnumerator()) {
  '{0,-6}: {1}' -f $i.Name, "$($i.Value)"
}



Время: 18:03.

Время: 18:03.
© OSzone.net 2001-