Форум программистов, компьютерный форум, киберфорум
Наши страницы
PowerShell
Войти
Регистрация
Восстановить пароль
 
reanimator133
0 / 0 / 0
Регистрация: 01.02.2016
Сообщений: 7
#1

Выделить, отсортировать и проверить на непрерывность номера из имён каталогов

01.02.2016, 20:14. Просмотров 446. Ответов 13
Метки нет (Все метки)

В результате работы некоего софта в директории создается набор папок вида:

abcdefgh_10051vxyz
bcdhgetyujh_10052vxyz
qwefds_10053vxyz

и т.д. всего от нескольких сотен до нескольких тысяч штук. Номера идут последовательно друг за другом с инкрементом.
Нужно:
- видеть весь массив номеров очищенный от первого и второго буквенных слагаемых, в колонку по возрастанию сверху вниз
- пересчитать номера : слева от каждого номера - его порядковый номер начиная с 1
- проверять непрерывность номеров, т.е кажый номер начиная с 2го больше предыдущего на единицу, если нет - предупреждение

В итоге должно получится:

1 10051
2 10052 ок
3 10053 ок
4 10055 Внимание пропущен номер!

Пока решил только первую задачу, номера успешно выдергивает из имен, выводит в колонку и сортирует по возрастанию скрипт вида:

PowerShell
1
dir -name | foreach-object {$_.PSChildName -match "/d+" | %{$matches[0]}} | sort-object
А как прикрутить порядковые номера и проверку непрерывности что то не могу дотумкать. Не силен в powershell.
Ну и в идеале все это должно в файл писаться. Но для начала хотя бы в окне сделать.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.02.2016, 20:14
Ответы с готовыми решениями:

Копирование файлов с сохранением имён каталогов
Доброго времени суток. В батниках я полный ноль. Но не взирая на это,...

Оповещения в файловой системе, отловить изменения имён каталогов
Здравствуйте . Есть такая задача: Проанализировать подкаталоги в каталоге ....

Вывод списка имён каталогов и поиск в этих каталогах файлов с определёнными расширениями
Всем привет, прошу прощения , но в программировании я полный ноль, нужной мне...

Проверить функцию на непрерывность
Пожайлуста помогите умные люди!!!! :) Что то я запуталась. :( Подскажите...

Проверить непрерывность на множестве
Проверить непрерывность на указанном множестве функции F(\alpha) =...

13
KDE777
714 / 529 / 227
Регистрация: 22.01.2016
Сообщений: 1,486
01.02.2016, 21:17 #2
reanimator133,

Дано:

abcdefgh_10051vxyz
bcdhgetyujh_10052vxyz
qwefds_10053vxyz
gfhytju_10055vxyz
ethfkfdg_10056vxyz
lkfgo_10059vxyz
dfpotdsf_10060vxyz
dogfiregfdv_10063vxyz

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$i = 0
$preItem = 0
 
foreach ($Item in (Get-ChildItem -Path C:\Temp\_Files -Recurse | ? PSIsContainer | Select @{name="Name"; Expression = {[int]($_.Name -replace '\D','')}} | sort name))
{
    
    if ((($Item.Name - $preItem) -gt 1) -and ($i -ne 0))
        {
        Write-Host ($i+=1) $Item.Name "Внимание пропущен номер!"
        }
    else
        {
        Write-Host ($i+=1) $Item.Name "Ok"
        }
    $preItem = $Item.Name
 
}
Получилось:

1 10051 Ok
2 10052 Ok
3 10053 Ok
4 10055 Внимание пропущен номер!
5 10056 Ok
6 10059 Внимание пропущен номер!
7 10060 Ok
8 10063 Внимание пропущен номер!

Добавлено через 9 минут
reanimator133, а это с сохранением в результатов в csv-файл:

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ResultFile = 'C:\Temp\result.csv'
$i = 0
$preItem = 0
 
Set-Content -Path $ResultFile -Value "NN;Name;Status" -Encoding UTF8
 
foreach ($Item in (Get-ChildItem -Path C:\Temp\_Files -Recurse | ? PSIsContainer | Select @{name="Name"; Expression = {[int]($_.Name -replace '\D','')}} | sort name))
{
    
    if ((($Item.Name - $preItem) -gt 1) -and ($i -ne 0))
        {
        $data = ($i+=1),$Item.Name,"Внимание пропущен номер!" -join ';'
        }
    else
        {
        $data = ($i+=1),$Item.Name,"OK" -join ';'
        }
    Add-Content -Path $ResultFile -Value $data -Encoding UTF8
    $preItem = $Item.Name
 
}
1
reanimator133
0 / 0 / 0
Регистрация: 01.02.2016
Сообщений: 7
01.02.2016, 21:57  [ТС] #3
скрипт без сохранения в файл выдает ошибку:
0
Миниатюры
Выделить, отсортировать и проверить на непрерывность номера из имён каталогов  
KDE777
714 / 529 / 227
Регистрация: 22.01.2016
Сообщений: 1,486
01.02.2016, 22:03 #4
reanimator133, попробуйте так (изменил строку №4) и какая у вас версия PS?

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$i = 0
$preItem = 0
 
foreach ($Item in (Get-ChildItem -Path "C:\Temp\_Files" -Recurse | Where {$_.PSIsContainer} | Select @{name="Name"; Expression = {[int]($_.Name -replace '\D','')}} | Sort name))
{
    
    if ((($Item.Name - $preItem) -gt 1) -and ($i -ne 0))
        {
        Write-Host ($i+=1) $Item.Name "Внимание пропущен номер!"
        }
    else
        {
        Write-Host ($i+=1) $Item.Name "Ok"
        }
    $preItem = $Item.Name
 
}
1
reanimator133
0 / 0 / 0
Регистрация: 01.02.2016
Сообщений: 7
01.02.2016, 22:16  [ТС] #5
вторая, тоже об этом подумал. Сейчас попробую поставить 3.0.
Win7 x32
0
KDE777
714 / 529 / 227
Регистрация: 22.01.2016
Сообщений: 1,486
01.02.2016, 22:28 #6
reanimator133, в 2.0 скорректированный вариант должен работать...

Я смотрю вы скрипт запускаете сразу в консоли, а это очень не удобно. Попробуйте использовать PowerShell ISE

А пока, для консоли - вот всё в одну строчку:

PowerShell
1
$i=0;$preItem=0;ls "C:\Temp\_Files" -R|?{$_.PSIsContainer}|Select @{name="Name";Expression={[int]($_.Name -replace '\D')}}|Sort name|%{if((($_.Name-$preItem)-gt 1)-and($i-ne 0)){Write-Host ($i+=1) $_.Name "Внимание!"}else{Write-Host($i+=1) $_.Name "Ok"};$preItem=$_.Name}
0
reanimator133
0 / 0 / 0
Регистрация: 01.02.2016
Сообщений: 7
01.02.2016, 22:38  [ТС] #7
Большое спасибо.
Заработал нескорректированный вариант после установки powershell версии 3.0. Не хотел ставится, гад, пока не установил framework 4.6.1.
0
KDE777
714 / 529 / 227
Регистрация: 22.01.2016
Сообщений: 1,486
01.02.2016, 22:43 #8
reanimator133, В 3.0 упростили синтаксис и вместо:

PowerShell
1
ls 'C:\Temp\_Files' -R | ? {$_.PSIsContainer}
можно просто написать:

PowerShell
1
ls 'C:\Temp\_Files' -R | ? PSIsContainer
1
reanimator133
0 / 0 / 0
Регистрация: 01.02.2016
Сообщений: 7
01.02.2016, 22:54  [ТС] #9
Ясно, спасибо за разъснение.

Можно чуть усложнить задачу:

abcdefgh_10051vxyz
bcdhgetyujh_10052vxyz
qwefds_10053vxyz
gfhytju_1005455vxyz
ethfkfdg_10056vxyz
lkfgo_10059vxyz
gybbhunu_100606162vxyz

Среди номеров изредка попадаются сдвоенные и строенные, т.е 10054 и 10055 как 1005455, 10060, 10061 и 10062 как 100606162.
Как учесть такую особенность?
0
KDE777
714 / 529 / 227
Регистрация: 22.01.2016
Сообщений: 1,486
02.02.2016, 00:42 #10
reanimator133,

В каком диапазоне находятся "нормальные" номера? Всегда пятизначные?
Сдвоенные и строенные - это всегда + одна или две пары из первых цифр нужного числа?

Добавлено через 10 минут
и может быть, например такой случай?

100990001 - 10099, 10100, 10101

Добавлено через 1 час 17 минут
reanimator133, если просто взять папки из вашего "усложнённого" примера (пока вы не уточнили условия) - получилось так:

abcdefgh_10051vxyz
bcdhgetyujh_10052vxyz
qwefds_10053vxyz
gfhytju_1005455vxyz
ethfkfdg_10056vxyz
lkfgo_10059vxyz
gybbhunu_100606162vxyz

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$i = 0
$preItem = 0
$numbers = @()
 
foreach ( $sample in (Get-ChildItem -Path "C:\Temp\_Files" -Recurse | ? {$_.PSIsContainer} | Select @{name="Name"; Expression = {$_.Name -replace '\D'}}) )
{
 
$str = $sample.name
if ($str.Length -gt 5)
    {
    $str.Substring(3) -split '(..)' | ?{$_} | % {$numbers+= [int]($str.Substring(0,3) + $_)}
    }
else
    {
    $numbers+= [int]$str
    }
 
}
 
foreach ( $Item in ($numbers | sort) )
{
    
if ((($Item - $preItem) -gt 1) -and ($i -ne 0))
    {
    Write-Host ($i+=1) $Item "Внимание пропущен номер!"
    }
else
    {
    Write-Host ($i+=1) $Item "Ok"
    }
$preItem = $Item
 
}
1 10051 Ok
2 10052 Ok
3 10053 Ok
4 10054 Ok
5 10055 Ok
6 10056 Ok
7 10059 Внимание пропущен номер!
8 10060 Ok
9 10061 Ok
10 10062 Ok

Хотя уверен, что кто-нибудь предложит что-то поизящнее..
0
reanimator133
0 / 0 / 0
Регистрация: 01.02.2016
Сообщений: 7
02.02.2016, 13:36  [ТС] #11
Номера в данный момент всегда пятизначные. Такой случай - быть может (100990001). Максимально бывают счетверенные номера. Спятиренных уже нет.

Разбивать сдвоенные-строенные-счетверенные номера нежелательно. Нужно чтобы они оставались в столбце:

1 10051 Ok
2 10052 Ok
3 10053 Ok
4 10054 Ok
5 10055 Ok
6 10056 Ok
7 10059 Внимание пропущен номер!
8 100606162 Ok
9 10063 Ok
10 10064 Ok
11 10065 Ok
12 10067 Внимание пропущен номер!

Добавлено через 44 минуты
Ну и в идеале, помимо основной колонки получить список пропущенных номеров, и сдвоенных-строенных-счетверенных. То есть так:

1 10050 Ok
2 1005152 Ok
3 10053 Ok
4 10054 Ok
5 10055 Ok
6 10056 Ok
7 10059 Внимание пропущен номер!
8 100606162 Ok
9 10063 Ok
10 10064 Ok
11 10065 Ok
12 10067 Внимание пропущен номер!

Пропущеные номера:

1 10057
2 10058
3 10066

Объединённые номера:

1 1005152
2 100606162
0
KDE777
714 / 529 / 227
Регистрация: 22.01.2016
Сообщений: 1,486
02.02.2016, 13:55 #12
reanimator133, в таком случае я пас, т.к. слишком трудоёмко...

Получается нужно учитывать очень много ситуаций, например такую 100990001 или такую 10097990001,

или даже такую 19999000102, где имеется в виду, что

19999
20000
пропущено 100 номеров
20101
20102

+ сортировать преобразованные номера для выявления пропусков, а затем в этой цепочке опять восстанавливать склеенные случаи...
0
reanimator133
0 / 0 / 0
Регистрация: 01.02.2016
Сообщений: 7
02.02.2016, 15:50  [ТС] #13
Все равно спасибо

Добавлено через 6 минут
В склееных номерах пропусков быть не может. Такое невозможно:

19999000102, где имеется в виду, что

19999
20000
пропущено 100 номеров
20101
20102

Тут однозначная трактовка как:

19999
20000
20001
20002

Добавлено через 10 минут

А если без склееных случаев:

НЕ ТАК:

1 10050 Ok
2 1005152 Ok
3 10053 Ok
4 10054 Ok
5 10055 Ok
6 10056 Ok
7 10059 Внимание пропущен номер!
8 100606162 Ok
9 10063 Ok
10 10064 Ok
11 10065 Ok
12 10067 Внимание пропущен номер!

Пропущеные номера:

1 10057
2 10058
3 10066

Объединённые номера:

1 1005152
2 100606162

А ВОТ ТАК:

1 10051 Ok
2 10052 Ok
3 10053 Ok
4 10054 Ok
5 10055 Ok
6 10056 Ok
7 10059 Внимание пропущен номер!
8 10060 Ok
9 10061 Ok
10 10062 Ok
10 10063 Ok
11 10064Ok
12 10065 Ok
13 10067 Внимание пропущен номер!

Пропущеные номера:

1 10057
2 10058
3 10066

Объединённые номера:

1 10051,10052
2 10060,10061, 10062
0
KDE777
714 / 529 / 227
Регистрация: 22.01.2016
Сообщений: 1,486
03.02.2016, 12:00 #14
Цитата Сообщение от reanimator133 Посмотреть сообщение
В склееных номерах пропусков быть не может. Такое невозможно
Цитата Сообщение от reanimator133 Посмотреть сообщение
А ВОТ ТАК:
тогда можно попробовать:

Кликните здесь для просмотра всего текста

abcdefgh_10051vxyz
bcdhgetyujh_10052vxyz
dfgdfgdfty_10064vxyz
dghghtyuty_10097989900vxyz
dsfgtrujgn_1010405vxyz
ethfkfdg_10056vxyz
gfhytju_1005455vxyz
gsdggsdg_10063vxyz
gybbhunu_100606162vxyz
hjyurdg_10103vxyz
lkfgo_10058vxyz
qwefds_10053vxyz


PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
$i = 0
$preItem = 0
$numbers = @()
 
$samples = Get-ChildItem -Path "C:\Temp\_Files" -Recurse | ? {$_.PSIsContainer} | Select @{name="Name"; Expression = {$_.Name -replace '\D'}}
 
foreach ( $sample in $samples )
{
 
$str = $sample.name
if ($str.Length -gt 5)
    {
    $base = [int]$str.Substring(0,3)
    $str.Substring(3) -split '(..)' | ?{$_} | % {       
        $numbers+= [int]($base.ToString() + $_)
        [int]$testBase = ($numbers[-1]+1).ToString().Substring(0,3)
        if ($testBase -ne $base) {$base = $testBase}}
    }
else
    {
    $numbers+= [int]$str
    }
 
}
 
foreach ( $Item in ($numbers | sort) )
{
    
if ((($Item - $preItem) -gt 1) -and ($i -ne 0))
    {
    Write-Host ($i+=1) $Item "Внимание пропущен номер!"
    }
else
    {
    Write-Host ($i+=1) $Item "Ok"
    }
$preItem = $Item
 
}
 
$missedItem = 0
$preItem = 0
$i = 0
$j = 0
 
Write-Host "`nПропущенные номера:"
foreach ( $Item in ($numbers | sort) )
{
 
if ((($Item - $preItem) -gt 1) -and ($i -ne 0))
    {
    $missedItem = $preItem + 1
    while($missedItem -ne $Item)
        {
        Write-Host ($j+=1) $missedItem
        $missedItem+= 1
        }
    }
 
$i+=1
$preItem = $Item
 
}
 
$numbers = @()
$i = 0
Write-Host "`nОбъединённые номера:"
foreach ( $sample in ($samples | ?{$_.Name.Length -gt 5}) )
{
 
$str = $sample.name
$base = [int]$str.Substring(0,3)
Write-Host ($i+=1) ":" -NoNewline
 
$str.Substring(3) -split '(..)' | ?{$_} | % {       
    $numbers += [int]($base.ToString() + $_)
    [int]$testBase = ($numbers[-1]+1).ToString().Substring(0,3)
    if ($testBase -ne $base) {$base = $testBase}}
 
Write-Host ($numbers -join ',')
$numbers = @()
 
}
Кликните здесь для просмотра всего текста

1 10051 Ok
2 10052 Ok
3 10053 Ok
4 10054 Ok
5 10055 Ok
6 10056 Ok
7 10058 Внимание пропущен номер!
8 10060 Внимание пропущен номер!
9 10061 Ok
10 10062 Ok
11 10063 Ok
12 10064 Ok
13 10097 Внимание пропущен номер!
14 10098 Ok
15 10099 Ok
16 10100 Ok
17 10103 Внимание пропущен номер!
18 10104 Ok
19 10105 Ok

Пропущенные номера:
1 10057
2 10059
3 10065
4 10066
5 10067
6 10068
7 10069
8 10070
9 10071
10 10072
11 10073
12 10074
13 10075
14 10076
15 10077
16 10078
17 10079
18 10080
19 10081
20 10082
21 10083
22 10084
23 10085
24 10086
25 10087
26 10088
27 10089
28 10090
29 10091
30 10092
31 10093
32 10094
33 10095
34 10096
35 10101
36 10102

Объединённые номера:
1 :10097,10098,10099,10100
2 :10104,10105
3 :10054,10055
4 :10060,10061,10062


Добавлено через 18 часов 52 минуты
Цитата Сообщение от reanimator133 Посмотреть сообщение
А если без склееных случаев
Cделал вариант, где выводится результат проверки со склеенными случаями:

Кликните здесь для просмотра всего текста

abcdefgh_10051vxyz
bcdhgetyujh_10052vxyz
dfgdfgdfty_10064vxyz
dghghtyuty_10097989900vxyz
dsfgtrujgn_1010405vxyz
ethfkfdg_10056vxyz
gfhytju_1005455vxyz
gsdggsdg_10063vxyz
gybbhunu_100606162vxyz
hjyurdg_10103vxyz
lkfgo_10058vxyz
qwefds_10053vxyz


PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
$samples = Get-ChildItem -Path "C:\Temp\_Files" -Recurse | ? {$_.PSIsContainer} | Select @{name="Name"; Expression = {$_.Name -replace '\D'}}
$numbers = @()
foreach ( $sample in $samples )
{
 
$str = $sample.name
 
if ($str.Length -gt 5)
    {
    $base = [int]$str.Substring(0,3)
    $str.Substring(3) -split '(..)' | ?{$_} | % {
        $numbers += @([pscustomobject]@{Number=[int]($base.ToString() + $_);Sample=$str;Status='?'})
        [int]$testBase = ($numbers[-1].Number+1).ToString().Substring(0,3)
        if ($testBase -ne $base) {$base = $testBase}}
    }
else
    {
    $numbers += @([pscustomobject]@{Number=[int]$str;Sample=$str;Status='?'})
    }
 
}
 
$j = 0
$preNumber = 0
$preSample =''
$index = @()
$numbers |%{$index+=$_.number}
 
foreach ( $Item in ($numbers | sort Number) )
{
 
$i = [array]::indexof($index,$Item.Number)
 
if ((($Item.Number - $preNumber) -gt 1) -and ($j -ne 0))
    {
    $numbers[$i].Status = "Пропущен номер!"
    if ($item.Sample -ne $preSample) {Write-Host ($j+=1) $item.Sample "Пропущен номер!"}
    }
else
    {
    $numbers[$i].Status = "Ok"
    if ($item.Sample -ne $preSample) {Write-Host ($j+=1) $item.Sample "Ok"}
    }
$preNumber = $Item.Number
$preSample = $item.Sample
 
}
 
$preItem = 0
$i = 0
$j = 0
 
Write-Host "`nПропущенные номера:"
foreach ( $Item in ($numbers | sort Number) )
{
 
if ((($Item.Number - $preItem) -gt 1) -and ($i -ne 0))
    {
    ($preItem+1)..($item.Number-1) | %{Write-Host ($j+=1) $_}
    }
$i+=1
$preItem = $Item.Number
 
}
 
$join = @()
$i = 0
Write-Host "`nОбъединённые номера:"
foreach ( $sample in ($samples | ?{$_.Name.Length -gt 5}) )
{
 
$str = $sample.name
$base = [int]$str.Substring(0,3)
Write-Host ($i+=1) ": " -NoNewline -Separator ''
 
$str.Substring(3) -split '(..)' | ?{$_} | % {
    $join += [int]($base.ToString() + $_)
    [int]$testBase = ($join[-1]+1).ToString().Substring(0,3)
    if ($testBase -ne $base) {$base = $testBase}}
 
Write-Host ($join -join ',')
$join = @()
 
}
Кликните здесь для просмотра всего текста

1 10051 Ok
2 10052 Ok
3 10053 Ok
4 1005455 Ok
5 10056 Ok
6 10058 Пропущен номер!
7 100606162 Пропущен номер!
8 10063 Ok
9 10064 Ok
10 10097989900 Пропущен номер!
11 10103 Пропущен номер!
12 1010405 Ok

Пропущенные номера:
1 10057
2 10059
3 10065
4 10066
5 10067
6 10068
7 10069
8 10070
9 10071
10 10072
11 10073
12 10074
13 10075
14 10076
15 10077
16 10078
17 10079
18 10080
19 10081
20 10082
21 10083
22 10084
23 10085
24 10086
25 10087
26 10088
27 10089
28 10090
29 10091
30 10092
31 10093
32 10094
33 10095
34 10096
35 10101
36 10102

Объединённые номера:
1: 10097,10098,10099,10100
2: 10104,10105
3: 10054,10055
4: 10060,10061,10062
0
03.02.2016, 12:00
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.02.2016, 12:00

Проверить на непрерывность функцию
u=7x-11y^2+3 в прямоугольнике П(x,y) , где -бесконечн.<x<+бесконечн. , |y|<2

Проверить на непрерывность функцию, заданную интегралом, зависящим от параметра
Доброго времени суток, господа! Помогите, пожалуйста, разобраться с задачей:...

Подсчитать число каталогов в родительском каталоге, затем напечатать их имена и номера индексных дескрипторов
Есть задача подсчитать число каталогов в родительском каталоге, затем...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru