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

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] [Вопрос новичка] Ошибка в скрипте PowerShell (http://forum.oszone.net/showthread.php?t=343812)

coollogan 26-01-2020 12:32 2906987

[Вопрос новичка] Ошибка в скрипте PowerShell
 
Доброго времени суток, уважаемые форумчане! Прошу прощения, если этой темой нарушил какое-то правило форума, если подобный вопрос уже был или решение покажется вам слишком очевидным, первый раз использую 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 2906993

Код:

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 2907032

Цитата:

Цитата Iska
Group-Object »

Какой прекрасный командлет, я и забыл про него.

coollogan 27-01-2020 08:49 2907073

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

Busla 27-01-2020 11:01 2907083

coollogan, построчное чтение файла - медленная операция

попробуйте заменить первую строку на
Код:

(Get-Content -Path 'C:\Мои проекты\0297\0002.txt' -Raw) -split "`n" | `

DJ Mogarych 27-01-2020 17:43 2907163

Медленное не построчное чтение, а группировка такого здоровенного массива.

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

Serguei Kouzmine 27-01-2020 18:25 2907188

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 2907236

Цитата:

Цитата coollogan
файл с 1040000 строк »

Не могли бы этот файл мне отправить на маил: v79italya@gmail.com Попробую для сравнения в Power Query обработать

DJ Mogarych 27-01-2020 23:17 2907244

Я сгенерировал файл в миллион строк командой
Код:

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

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мб..

Цитата:

Цитата Serguei Kouzmine
а просто использовать немного перереботанный оригиналиный скрипт не хотите ? »

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

Iska 28-01-2020 14:43 2907331

Цитата:

Цитата coollogan
загрузил файл для теста на диск: yadi.sk/d/a4DIRzf2qCISYg (надеюсь на форуме разрешено делиться ссылками на текстовые документы) »

coollogan, упакуйте Ваш текстовый файл в архив.

coollogan 28-01-2020 15:32 2907339

Цитата:

Цитата Iska
coollogan, упакуйте Ваш текстовый файл в архив. »

Iska, готово: https://yadi.sk/d/0cw4wmiQITeQww

DJ Mogarych 28-01-2020 15:46 2907342

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

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

coollogan 28-01-2020 15:57 2907344

Цитата:

Цитата DJ Mogarych
Необходимо дождаться окончания работы скрипта »

Спасибо, будем пробовать, смущало что в этот момент ничего не происходит, ни статус-бара, ни логов, ничего)
Следующий на обработку файл – 147мб, боюсь представить сколько времени займет процесс.

DJ Mogarych 28-01-2020 16:53 2907358

Ну, можно, наверное, намутить какой-то вывод в консоль процесса, но это ещё больше растянет время обработки.

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 2907381

DJ Mogarych, большое спасибо за помощь)

Iska 28-01-2020 19:05 2907394

Цитата:

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

Это как всегда ;).


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

Iska 28-01-2020 20:16 2907410

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 так:
Скрытый текст

с сортировкой — чуть больше двадцати секунд (без сортировки — чуть больше пятнадцати секунд).

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

coollogan 28-01-2020 22:01 2907432

Цитата:

Цитата Iska
Это как всегда . »

Ктож знал, что есть отличия) За то теперь запомню точно))

Цитата:

Цитата Iska
Вам действительно нужен подсчёт количества повторов? »

Да, задача такая, нужно собрать топ ±3000 повторяющихся строк из списка)

Цитата:

Цитата Iska
можете попробовать на WSH (используем OLE DB): »

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

Iska 28-01-2020 23:12 2907437

Цитата:

Цитата coollogan
начну с того, что такое 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, находясь в окне интерпретатора команд.

YuS_2 30-01-2020 07:38 2907577

Цитата:

Цитата coollogan
Да, задача такая, нужно собрать топ ±3000 повторяющихся строк из списка) »

т.е. остальные записи не нужны совсем?
Тогда:
1. Установите powershell core, лучше крайнюю версию (7.0). В powershell core командлет group-object был оптимизирован и работает гораздо быстрее, чем в версиях PS 5.1 и ниже. В общем, для получения адекватного времени обработки, необходимо использовать свежую версию powershell.
2. Если откидывать уникальные строки, то можно код оптимизировать (у меня отрабатывает на Вашем файле ps.txt, примерно 50-55 сек.):

Код:

measure-command{
        $in = 'ps.txt'
        $out = 'ps.csv'
        $arr = gc $in -r 0 -enc utf8|%{$_|sort}
        $arrnum = for ($i=1;$i -lt $arr.count;$i++){
                if($arr[$i] -eq $arr[($i-1)]){$i;$i-1}
        }
        $arrsnum = $arrnum|sort -uni
        $arrresult = for($i=0;$i -lt $arrsnum.count;$i++){
                $arr[($arrsnum[$i])]
        }
        $arrresult|group -noel |select name,count|sort count -d|
        export-csv $out  -notype -enc utf8
}


DJ Mogarych 30-01-2020 10:22 2907601

Цитата:

Цитата YuS_2
В powershell core командлет group-object был оптимизирован и работает гораздо быстрее, чем в версиях PS 5.1 и ниже. »

Подтверждаю!
Файл обрабатывался минут 15 на моей машине в Powershell 7 RC2. Окончания работы PS 5.1 я ждал почти сутки, но так и не дождался.

В целом, код такой:
Код:

(gc C:\temp\PS.txt |group -noel |select name,count).where{$_.count -ge 3000} |sort count -desc |Export-Csv C:\temp\PS.txt ';' -NoType

v79italya 30-01-2020 19:54 2907683

coollogan, попробуйте в Excel. Поменять путь до файла и нажать Ctrl+Alt+F5
У меня выгружало около минуты.
Выгрузит адреса с наибольшими повторениями (3000 адресов)

coollogan 31-01-2020 10:16 2907753

Друзья, YuS_2, v79italya, DJ Mogarych, Serguei Kouzmine, Busla, ВСЕМ ВАМ ОГРОМНОЕ СПАСИБО!

Не ожидал такой помощи, сейчас буду пробовать все варианты)

Цитата:

Цитата v79italya
попробуйте в Excel. Поменять путь до файла и нажать Ctrl+Alt+F5 »

А Ctrl+Alt+F5 какую функцию выполняет? Хочу попробовать на mac, не помогает, а гуглеж такой горячей клавиши не находит.

v79italya 31-01-2020 15:54 2907778

Цитата:

Цитата coollogan
Ctrl+Alt+F5 какую функцию выполняет? »

Запускает запрос Power Query.
Забыл написать что Power Query встроена в Excel2016 и в Excel 365. Для Excel 2010-2013 надстройку Power Query надо скачивать отдельно. И все это на Windows.
Насчет Excel на Mac мне ничего не известно
здесь внизу есть и про Mac
HTML код:

https://support.office.com/ru-ru/article/%D0%93%D0%B4%D0%B5-%D0%BD%D0%B0%D0%B9%D1%82%D0%B8-%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F-power-query-e9332067-8e49-46fc-97ff-f2e1bfa0cb16

coollogan 31-01-2020 16:43 2907782

v79italya, получилось сделать на удаленном рабочем столе! Реально за пару секунд все сделалось, шок! Спасибо!

v79italya 31-01-2020 17:00 2907784

Цитата:

Цитата coollogan
за пару секунд все сделалось »

Пожалуйста. Только, откровенно говоря, с трудом верится в эту скорость. У меня текстовый файл только читает секунд пятнадцать.
Попробуйте на другом текстовом файле, о котором вы говорили(147мб).

Iska 31-01-2020 17:05 2907785

v79italya, может, у него там SSD в чередовании?!

v79italya 31-01-2020 18:14 2907796

Iska, не ну хорошо если все так.
А я грешу на Power Query, типа медленно обрабатывает объемы данных. А надо оказывается на свою несостоятельность грешить, что не могу себе позволить какое нибудь мощное железо для компа. Или на место проживания грешить? Типа, в гиблом месте живу :)
Вообще то мне мой нэтбук с двумя гигами озу и с двумя ядрами процессора и неизвестно какой видяхой нравится. А че, куплен бу по цене аккамулятора и не планирую менять ближайшие лет пять. Вернее, в ближайшие лет пять не видятся никаких заработков, потому и не планируются покупки. Как то так :)

coollogan 02-02-2020 01:48 2907971

Цитата:

Цитата v79italya
Только, откровенно говоря, с трудом верится в эту скорость »

Перепроверил, файл 7мб сортирует за +- 3 секунды
На файл 148 мегабайт ушло секунд 15 :)

v79italya, а если возникнет необходимость получить больше 3 000 строк, я могу внести какие-то корректировки?

Цитата:

Цитата Iska
может, у него там SSD в чередовании?! »

не знаю SSD или HDD, но оперативки 32 ГБ ��
Дали попользоваться

v79italya 02-02-2020 13:52 2908001

Вложений: 1
coollogan, в ячейке рядом с адресом файла введите необходимое количество строк и обновите запрос

coollogan 24-03-2020 03:17 2914442

Цитата:

Цитата v79italya
coollogan, в ячейке рядом с адресом файла введите необходимое количество строк и обновите запрос »

Приветствую! Вернулся к вопросу и кажется что-то не работает, подскажите, файл как-то зависит от вас, не работает автономно?
Пишет ошибка инициализации к внешнему источнику данных.

v79italya 24-03-2020 06:56 2914447

coollogan, файл ко мне никак не привязан. Раз работал запрос на этой машине, то и сейчас должен работать. Другой вопрос, если в одном Excel2016 работает, а в другом Excel2016 не работает. Можно попробовать установить обновление для Excel и Power Queryhttps://www.catalog.update.microsoft...px?q=KB4462115

coollogan 24-03-2020 12:14 2914468

Цитата:

Цитата v79italya
файл ко мне никак не привязан. Раз работал запрос на этой машине, то и сейчас должен работать. Другой вопрос, если в одном Excel2016 работает, а в другом Excel2016 не работает. Можно попробовать установить обновление для Excel и Power Queryhttps://www.catalog.update.microsoft...px?q=KB4462115 »

Понял, да, скорее всего дело в Excel, пробовал на другой машине) Спасибо!


Время: 17:09.

Время: 17:09.
© OSzone.net 2001-