Войти

Показать полную графическую версию : Механизм замены части данных в Powershell


DJ Mogarych
20-09-2019, 21:49
Уважаемые товарищи, объясните мне, пожалуйста, одну вещь.

Вот есть какие-то данные, к примеру, список процессов, я их помещаю в переменную:

$src = get-process |select name,product,ProductVersion |? product -match "операционная система"
Результат:
Name Product ProductVersion
---- ------- --------------
explorer Операционная система Microsoft® Windows® 10.0.17763.769
smartscreen Операционная система Microsoft® Windows® 10.0.17763.769
svchost Операционная система Microsoft® Windows® 10.0.17763.769
svchost Операционная система Microsoft® Windows® 10.0.17763.769
svchost Операционная система Microsoft® Windows® 10.0.17763.769
svchost Операционная система Microsoft® Windows® 10.0.17763.769
SystemSettings Операционная система Microsoft® Windows® 10.0.17763.769
taskhostw Операционная система Microsoft® Windows® 10.0.17763.769

Дальше я беру и создаю переменную из куска предыдущих данных:

$piece = $src |? name -match smart
Результат:
Name Product ProductVersion
---- ------- --------------
smartscreen Операционная система Microsoft® Windows® 10.0.17763.769

Теперь я беру и меняю имя в этом куске:
$piece.name = "Умный экран"
Результат:
Name Product ProductVersion
---- ------- --------------
Умный экран Операционная система Microsoft® Windows® 10.0.17763.769

Теперь самое удивительное - если вывести содержимое первой переменной, где содержатся все данные, то имя из того куска, который вычленили, тоже будет изменено:
$src
Результат:
Name Product ProductVersion
---- ------- --------------
explorer Операционная система Microsoft® Windows® 10.0.17763.769
Умный экран Операционная система Microsoft® Windows® 10.0.17763.769
svchost Операционная система Microsoft® Windows® 10.0.17763.769
svchost Операционная система Microsoft® Windows® 10.0.17763.769
svchost Операционная система Microsoft® Windows® 10.0.17763.769
svchost Операционная система Microsoft® Windows® 10.0.17763.769
SystemSettings Операционная система Microsoft® Windows® 10.0.17763.769
taskhostw Операционная система Microsoft® Windows® 10.0.17763.769

Это очень удобно - можно, к примеру, менять загруженный в память CSV построчно по определённой выборке, но я не понимаю, почему, изменяя один объект, по идее, являющийся отдельным, меняется другой.

Кто-нибудь знаком с этим механизмом?

YuS_2
20-09-2019, 22:49
не понимаю, почему, изменяя один объект, по идее, являющийся отдельным, меняется другой. »
В powershell, массивы создаваемые оператором присваивания, работают по ссылке на один и тот же объект.
Изменение размера массива, фактически создает новый массив и в этом случае, они уже не будут взаимосвязанными.
Для иллюстрации:
$a=,1
$b=$a
$b[0]=3
$a
$b+=1
$b[0]=10
$a

Iska
20-09-2019, 23:30
DJ Mogarych, как верно сказал коллега YuS_2, это поведение зависит от того, что происходит в конкретном языке при реализации операции присваивания объектных переменных в том или ином случае. В приведённом Вами случае, надо полагать, что некоей переменной X, стоящей слева от оператора присваивания, присваивается ссылка на ту же самую коллекцию объектов (в памяти), на которую ссылается некая переменная Y, которая находится справа от оператора присваивания. Где-то этим поведением можно управлять явно, где-то — неявно, а где-то — управлять вовсе нельзя (как было задано создателями языка, так, мол, и пользуйте).

DJ Mogarych
21-09-2019, 07:45
Получается, что без изменения размеров область памяти одна, и переменные работают как фильтр, а если изменить размер, системе приходится создавать новый объект?

Busla
21-09-2019, 10:42
Изменение размера массива, фактически создает новый массив »
в PowerShell массивы фиксированного размера, поэтому никакого изменения размера массива попросту нет. Операция массив + что-то возвращает новый массив.

если изменить размер, системе приходится создавать новый объект »
система никаких решений не принимает, набор операция для каждого типа определён заранее

К сожалению, что и как реализовано можно только выучить.

YuS_2
21-09-2019, 12:28
Операция массив + что-то возвращает новый массив. »
Уважаемый, вы если решили поумничать на пустом месте, то вчитайтесь в то, что написано выше, а именно в то, что вы процитировали...
Что вы хотели сказать - непонятно, ибо написали то же самое, что написано в цитате, просто другими словами... нет?

Busla
21-09-2019, 13:42
написали то же самое, что написано в цитате, просто другими словами... нет? »
нет
я описал реализацию, а вы - магию
очень показательно, как ваше "то же самое" воспринял топикстартер:
Получается, что без изменения размеров область памяти одна, и переменные работают как фильтр, а если изменить размер, системе приходится создавать новый объект? »

размер тут не при чём
для списков определена операция добавления:
> $a = New-Object 'System.Collections.Generic.List[int]'
> $a.Add(4)
> $b=$a
> $a.Add(4)
> $b
4
4

и изменение размера ни к каким пересозданиям не приводит

DJ Mogarych
21-09-2019, 14:54
Операция массив + что-то возвращает новый массив. »
Тогда как объяснить ситуацию, описанную мной в самом начале?

YuS_2
21-09-2019, 15:13
я описал реализацию »
Да что вы говорите?! Отлично!
Самомнение у вас раздуто сильно.
Если уж беретесь кулаком в грудь стучать, то описывайте не косноязычно:
Операция массив + что-то возвращает новый массив. »
Такое описание даже на сказку не тянет, не то что на магию, если что...
Что это за операция такая "Плюс что-то"? :)

для списков определена операция добавления: »
При чем тут списки вообще? Вы только себя читаете, а вопросы по диагонали?
Там самый обычный массив:
$src = get-process |select name,product,ProductVersion »
PS_5.1> $src = get-process |select name,product,ProductVersion
PS_5.1> $src.gettype()

IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
Попробуйте проделать то же самое с объектом System.Array, т.е.:
$a = ,1
$a.add(4)
- что получите в результате?

А потом проверьте:
$a.length
$a+=8
$a.length
- для конечного пользователя, это суть "изменение" размера массива, хоть и внутри это работает по-другому, о чем и было сказано.
Вы же полезли на какой-то рожон и решили поумничать.
Бог вам судья, пишите ещё...

Busla
21-09-2019, 21:25
При чем тут списки вообще? Вы только себя читаете, а вопросы по диагонали? »
как раз наоборот: вы что-то сказали, а не можете принять, что ваши слова кто-то интерпретирует иначе
и самомнение раздуто у вас
помимо вас тут есть ещё люди, и они тоже что-то пишут

списки это пример того, что вывод из ваших слов получился неверный:
переменные работают как фильтр, а если изменить размер, системе приходится создавать новый объект »

как объяснить ситуацию, описанную мной в самом начале? »
Нагляднее всего это проявляется в языках более низкого уровня с прямым управлением памятью: Си, Паскаль - там типы значений и ссылочные типы (указатели) имеют разный синтаксис.

список процессов, я их помещаю в переменную »
на самом деле это список ссылок на объекты процессов, а в переменной не список, а ссылка на него
Операции над списком ссылок сами объекты процессов не затрагивают, точно так же как и изменение отдельного свойства объекта не копирует и не замещает весь объект. Ссылка на него остаётся той же.

DJ Mogarych
22-09-2019, 11:05
Спасибо ВСЕМ, буду осмысливать!

YuS_2
22-09-2019, 14:26
списки это пример того, что вывод из ваших слов получился неверный »
В огороде бузина, а в Киеве - дядька.
Не морочьте голову ни себе, ни другим.
Массивы (а у ТС, как раз System.Array) в powershell имеют ссылочный тип (об этом написано в спецификации), о чем и было сказано в самом начале. Вы же полезли в бутылку, чтобы это как-то оспорить - хотя о чем тут спорить? Вы утверждаете, что-то другое? Вижу, что нет. Тогда к чему был ваш комментарий (http://forum.oszone.net/post-2888924.html#post2888924) с цитатой моих слов, вы КО? :)
Не надо разводить здесь болота, чтобы пояснить эту простую вещь.
И приплетать Си, Паскаль, да и упоминать синтаксис - абсолютно бессмысленно...

PS
А на счет моего самомнения - вы заблуждаетесь, оно у меня в подписи обозначено.




© OSzone.net 2001-2012