PDA

Показать полную графическую версию : [решено] [Вопрос новичка] Ошибка в скрипте PowerShell


Страниц : [1] 2

coollogan
26-01-2020, 12:32
Доброго времени суток, уважаемые форумчане! Прошу прощения, если этой темой нарушил какое-то правило форума, если подобный вопрос уже был или решение покажется вам слишком очевидным, первый раз использую PowerShell и поиск по гуглу/форуму ничего не дал. Буду признателен за любую помощь в исполнении простого скрипта.

Задача: Есть текстовый документ, содержащий в себе данные типа:
1
2
1
2
1
4
1

Мне необходимо, чтобы PowerShell выдал мне информацию, что в текстовом документе:
1 - 3
2 - 2
4 - 1

Get-Content .\smm.txt | ForEach-Object -Begin { $wordCounts.@{} } -Process { $wordCounts.$_++ } -End { $wordCounts.GetEnumerator() | Sort-Object -Property Value }

и PowerShell возвращает мне следующую информацию:
Не удается найти свойство "2" для данного объекта. Убедитесь, что оно существует и его можно задать.
строка:1 знак:78
+ ... Object -Begin { $wordCounts.@{} } -Process { $wordCounts.$_++ } -End ...
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound

Не удается найти свойство "1" для данного объекта. Убедитесь, что оно существует и его можно задать.
строка:1 знак:78
+ ... Object -Begin { $wordCounts.@{} } -Process { $wordCounts.$_++ } -End ...
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound

Не удается найти свойство "2" для данного объекта. Убедитесь, что оно существует и его можно задать.
строка:1 знак:78
+ ... Object -Begin { $wordCounts.@{} } -Process { $wordCounts.$_++ } -End ...
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound

Не удается найти свойство "1" для данного объекта. Убедитесь, что оно существует и его можно задать.
строка:1 знак:78
+ ... Object -Begin { $wordCounts.@{} } -Process { $wordCounts.$_++ } -End ...
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound

Не удается найти свойство "4" для данного объекта. Убедитесь, что оно существует и его можно задать.
строка:1 знак:78
+ ... Object -Begin { $wordCounts.@{} } -Process { $wordCounts.$_++ } -End ...
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound

Не удается найти свойство "1" для данного объекта. Убедитесь, что оно существует и его можно задать.
строка:1 знак:78
+ ... Object -Begin { $wordCounts.@{} } -Process { $wordCounts.$_++ } -End ...
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound

Невозможно вызвать метод для выражения со значением NULL.
строка:1 знак:104
+ ... ++ } -End { $wordCounts.GetEnumerator() | Sort-Object -Property Value ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull


Еще по возможности, данные выгрузки необходимо сохранить в csv/любой другой файл с встречающимися словами и кол-вами повторений, чтобы была возможность их как-то сортировать и обрабатывать. Буду благодарен любой помощи в данном вопросе)

Iska
26-01-2020, 13:09
Get-Content -Path 'C:\Мои проекты\0297\0002.txt' | `
Group-Object | Select-Object -Property Name, Count | Sort-Object -Property Name | `
Export-Csv -NoTypeInformation -Path 'C:\Мои проекты\0297\0003.txt'

DJ Mogarych
26-01-2020, 21:21
Group-Object »
Какой прекрасный командлет, я и забыл про него.

coollogan
27-01-2020, 08:49
ISKA, Большое, человеческое, спасибо!
Еще такой вопрос, сколько примерно по времени должен обрабатываться файл с 1040000 строк? Запустил скрипт, прошел уже час, файл 003 создался сразу, но пустой, в PowerShell тишина, переживаю что ничего не происходит.

Busla
27-01-2020, 11:01
coollogan, построчное чтение файла - медленная операция

попробуйте заменить первую строку на
(Get-Content -Path 'C:\Мои проекты\0297\0002.txt' -Raw) -split "`n" | `

DJ Mogarych
27-01-2020, 17:43
Медленное не построчное чтение, а группировка такого здоровенного массива.

Может быть, полезно будет добавить к Group-Object флаг -NoElement, т. к. список элементов в данном случае не нужен.

Serguei Kouzmine
27-01-2020, 18:25
coollogan,
а просто использовать немного перереботанный оригиналиный скрипт не хотите ?

$wordCounts = @{}; Get-Content .\data.txt | ForEach-Object { $wordCounts[$_] ++ } ; $wordCounts.GetEnumerator() | Sort-Object -Property Value


Name Value
---- -----
4 1
2 2
1 4


for N in $(seq 1 1 10000) ; do cat data.txt >> bigdata.txt; done


$wordCounts = @{}; Get-Content .\bigdata.txt | ForEach-Object { $wordCounts[$_] ++ } ; $wordCounts.GetEnumerator() |
Sort-Object -Property Value


так же бысто

[CODE]
Name Value
---- -----
11 1691
4 1692
2 3384
1 3386
[/CODE ]

v79italya
27-01-2020, 21:54
файл с 1040000 строк »
Не могли бы этот файл мне отправить на маил: v79italya@gmail.com Попробую для сравнения в Power Query обработать

DJ Mogarych
27-01-2020, 23:17
Я сгенерировал файл в миллион строк командой

(1..1000000).foreach({get-random -InputObject (1..999)}) > c:\temp\million.txt


Вот этой командой всё отработало за 30,59 сек.

gc C:\temp\million.txt |group -noel |select name,count |sort @{e={$_.name -as [int]}} |Export-Csv C:\temp\numbers.csv ';' -NoType

А если убрать -NoElement, то за 63,91 сек. Логично - чем меньше данных прокачиваешь через конвейер и чем раньше фильтруешь данные, тем быстрее работает.

coollogan
28-01-2020, 11:22
v79italya, загрузил файл для теста на диск: yadi.sk/d/a4DIRzf2qCISYg (надеюсь на форуме разрешено делиться ссылками на текстовые документы)

DJ Mogarych, использовал код:
gc C:\temp\million.txt |group -noel |select name,count |sort @{e={$_.name -as [int]}} |Export-Csv C:\temp\numbers.csv ';' -NoType


Аналогично, как и в первом случае, у меня ничего не происходит, просто комп начинает шуметь. За час работы никаких изменений не произошло ��
Это связано с тем, что у меня не просто нули и единицы, а ссылки, я правильно понимаю? Следующий файл который я хотел обработать весит 147мб..

а просто использовать немного перереботанный оригиналиный скрипт не хотите ? »
Хочу) Но к сожалению вы имеете дело с дилетантом, по этому выслав мне 3 скрипта вы вызвали в моей голове системную ошибку)

Iska
28-01-2020, 14:43
загрузил файл для теста на диск: yadi.sk/d/a4DIRzf2qCISYg (надеюсь на форуме разрешено делиться ссылками на текстовые документы) »
coollogan, упакуйте Ваш текстовый файл в архив.

coollogan
28-01-2020, 15:32
coollogan, упакуйте Ваш текстовый файл в архив. »
Iska, готово: https://yadi.sk/d/0cw4wmiQITeQww

DJ Mogarych
28-01-2020, 15:46
coollogan, объём данных, который вы обрабатываете, весьма большой.
Необходимо дождаться окончания работы скрипта - да, он может работать несколько часов.
Если вы хотите быстрее, надо запускать на более мощном железе.

Либо, сначала модифицировать сам исходный файл, например, убрать https://www.instagram.com/, а оставлять только логины - это уменьшит время обработки, т. к. объём файла будет меньше.

coollogan
28-01-2020, 15:57
Необходимо дождаться окончания работы скрипта »
Спасибо, будем пробовать, смущало что в этот момент ничего не происходит, ни статус-бара, ни логов, ничего)
Следующий на обработку файл – 147мб, боюсь представить сколько времени займет процесс.

DJ Mogarych
28-01-2020, 16:53
Ну, можно, наверное, намутить какой-то вывод в консоль процесса, но это ещё больше растянет время обработки.

coollogan, я упустил одну важную вещь!
Уберите из скрипта

@{e={$_.name -as [int]}}


В изначальном условии вы давали цифры, а в результате обрабатываете нецифровые строки.

Так что
gc C:\temp\PS.txt |group -noel |select name,count |sort name |Export-Csv C:\temp\PS.csv ';' -NoType


Можно, чтобы было побыстрее, не сортировать, это можно будет сделать потом:

gc C:\temp\PS.txt |group -noel |Export-Csv C:\temp\PS.csv ';' -NoType

coollogan
28-01-2020, 18:00
DJ Mogarych, большое спасибо за помощь)

Iska
28-01-2020, 19:05
В изначальном условии вы давали цифры, а в результате обрабатываете нецифровые строки. »
Это как всегда ;).

coollogan, Вам действительно нужен подсчёт количества повторов? Может быть, задача проще, и Вам достаточно просто отобрать уникальные значения, без подсчёта повторов, не?!

Iska
28-01-2020, 20:16
coollogan, можете попробовать на WSH (используем OLE DB):
Option Explicit

Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = 1


Dim strSourceFile
Dim strDestFile
Dim strPath2Schema

Dim objRecordset

Dim dtStartDateTime


strSourceFile = "PS.txt"
strDestFile = "ResultFile.csv"

With WScript.CreateObject("Scripting.FileSystemObject")
strPath2Schema = .GetParentFolderName(WScript.ScriptFullName)

dtStartDateTime = Now()
WScript.Echo "Start at: " & CStr(dtStartDateTime)

If Not .FileExists(.BuildPath(strPath2Schema, "Schema.ini")) Then
With .CreateTextFile(.BuildPath(strPath2Schema, "Schema.ini"), True)
.Write _
"[" & strSourceFile & "]" & vbCrLf & _
"ColNameHeader=False" & vbCrLf & _
"CharacterSet=1251" & vbCrLf & _
"Format=Delimited(;)" & vbCrLf & _
"TextDelimiter=none" & vbCrLf & _
"Col1=Url Text" & vbCrLf & _
"" & vbCrLf & _
"[" & strDestFile & "]" & vbCrLf & _
"ColNameHeader=True" & vbCrLf & _
"CharacterSet=1251" & vbCrLf & _
"Format=CSVDelimited" & vbCrLf & _
"TextDelimiter=none" & vbCrLf & _
"Col1=Url Char Width 255" & vbCrLf & _
"Col2=Count Integer" & vbCrLf

.Close
End With
End If

If .FileExists(.BuildPath(strPath2Schema, strDestFile)) Then
.DeleteFile .BuildPath(strPath2Schema, strDestFile), True
End If

WScript.CreateObject("ADODB.Recordset").Open _
"SELECT S.[Url], COUNT(S.[Url]) AS [Count] INTO [" & strDestFile & "] " & _
"FROM [" & strSourceFile & "] AS S " & _
"GROUP BY S.[Url] " & _
"ORDER BY COUNT(S.[Url]) DESC", _
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strPath2Schema & ";Extended Properties=""text;""", _
adOpenStatic, adLockOptimistic, adCmdText

WScript.Echo "Finish at: " & CStr(Now())
WScript.Echo "Total: " & CStr(DateDiff("s", dtStartDateTime, Now())) & " second(s)."
End With

WScript.Quit 0

Поместите скрипт рядом с Вашим файлом PS.txt.

У меня получается на Вашем выложенном файле PS.txt так:
https://i.imgur.com/Dha7Mii.png
с сортировкой — чуть больше двадцати секунд (без сортировки — чуть больше пятнадцати секунд).

NB! Важное замечание: на x64 ОС нужно использовать x86-версии cscript.exe/wscript.exe, т.е., прямо указывать путь к ним из каталога C:\Windows\SysWOW64 (см. скриншот под спойлером выше).

coollogan
28-01-2020, 22:01
Это как всегда . »
Ктож знал, что есть отличия) За то теперь запомню точно))

Вам действительно нужен подсчёт количества повторов? »
Да, задача такая, нужно собрать топ ±3000 повторяющихся строк из списка)

можете попробовать на WSH (используем OLE DB): »
Спасибо! Завтра попробую изучить, начну с того, что такое WSH :cool:
Это встроенная функция как PowerShell, или можно её скачать? Мне советовали использовать AWK, чуть с ума не сошел изучая сайты которые хоть что-то пишут про него) Да пишут так, как будто первые 499 страниц инструкции куда-то делись, и начинается с пятисотой)) Понял, что не мой вариант, хотя там такой массив данных обрабатывался за несколько секунд тоже)

Iska
28-01-2020, 23:12
начну с того, что такое WSH »
1. Сохраните код в файл с расширением .vbs, получив скрипт WSH (Windows Script Host).
2. Расположите данный скрипт рядом с Вашим файлом PS.txt.
3. Вызовите скрипт на исполнение.

Если Ваша ОС — x64, то вместо пункта 3 будут следующие пункты:

3. Откройте интерпретатор команд: Win-R, «"%comspec%" /k», Enter.
4. Перетащите из окна Проводника в окно интерпретатора команд файл «C:\Windows\SysWOW64\cscript.exe».
5. Нажмите пробел, находясь в окне интерпретатора команд.
6. Перетащите из окна Проводника в окно интерпретатора команд скрипт WSH (файл с расширением .vbs), созданный в пп.1-2.
7. Нажмите Enter, находясь в окне интерпретатора команд.




© OSzone.net 2001-2012