PDA

Показать полную графическую версию : Select-String. Парсинг нескольких значений между наборами символов.


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


...
!--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
param(
$path = "C:\files\qwe.txt"
)cls

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

rango13
18-07-2020, 02:05
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
(gc C:\temp\test\text.txt) -replace "^.*?gt;" -replace "&lt;.*?$"

Sham
18-07-2020, 12:26
Регулярное выражение на всю группу строк с подмасками. Выводим подмаски.
$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
Скажите, можно ли в той конструкции, которую вы написали, использовать несколько условий »
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
Уже второй день бьюсь с задачей »
Задача разовая или периодическая, которая требует автоматизации? Лучше от этого отталкиваться...
Можете подтолкнуть в правильном направлении? »
Если говорить о правильном направлении, то лучше декодировать текст, чтобы получить валидный 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
(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
чтобы так выводить надо преобразовывать под определенный формат, для примера чтобы было понятно что я имею ввиду:

$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)"
}




© OSzone.net 2001-2012