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

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] использование && и || при готовом true или false (http://forum.oszone.net/showthread.php?t=348737)

Elven 13-05-2021 13:57 2957749

использование && и || при готовом true или false
 
Такс, кто мне объяснит за пошик у меня мозг слегка подвисать начал от того во что я уперся:
есть такой фрагмент на баше
Код:

~ /bin/true && echo "result: OK" || echo "result: KO"
result: OK

~ /bin/false && echo "result: OK" || echo "result: KO"
result: KO

и тут всё понятно, отдаем true или false и в зависимости от принятого выводим ОК или KO. пробуем сделать аналогично в пошике:
Код:

$true 2>&1>$null && Write-Host "result: OK" || Write-Host "result: KO"
result: OK

с этим всё путём, так и ожидалось. а теперь
Код:

$false 2>&1>$null && Write-Host "result: OK" || Write-Host "result: KO"
result: OK

втф? начал глубже копаться, добавил в вывод $? дык оказывается $? возвращает true и при $true, и при $false
Код:

$true 2>&1>$null && Write-Host "result: OK ($?)" || Write-Host "result: KO ($?)"
result: OK (True)
$false 2>&1>$null && Write-Host "result: OK ($?)" || Write-Host "result: KO ($?)"
result: OK (True)

у кого есть сцыль на то чтобы почитать что-то про это дело? ну или своими словами можно, я не привередливый.

фрагменты, разумеется, до крайности упрощенные, на самом деле там многоэтажная конструкция (или многопайповая?) результатом которой является либо "true" либо "false", но не в виде "$?", а просто сами по себе. разумеется я это всё дело заменил if, но как и зачем оно так работает таки интересно.

Elven 13-05-2021 16:01 2957763

upd: about_pipeline_chain_operators
Если кратко и по сути: есть то что мы передаем, а есть то что пошик читает. в данном случае мы передаем конкретное значение $true или $false, а пошик смотрит исключительно в $?
и на его взгляд вывод значения переменной $false как и $true вполне даже прошел успешно (т.е. вернул в $? - true) на основе чего и строятся условия этих pipeline chain operators (как бы это культурнее перевести? операторы цепочки конвейера? или просто операторы цепочки или операторы конвейера? - любой вариант режет слух). Не могу сказать что это хорошо, хотя и не могу утверждать что плохо. Это просто так, и никак иначе.

субъективное мнение: пошик создавался не за один день, было много на него накручено, когда я добрался до try catch finally - вообще полный восторг, наконец можно скрипт просто и элегантно завернуть в адекватную обработку ероров и/или ворнингов, настроить правильные постдействия... а теперь есть официальные примеры, в которых англицким по-белому написано (хоть и несколько иносказательно): забейте на ошибки, если они таки будут - вот вам || и радуйтесь этому как хотите. Ну а если ошибки нам неинтересны то и тем более &&

YuS_2 13-05-2021 18:48 2957776

Цитата:

Цитата Elven
или просто операторы цепочки или операторы конвейера? »

Как по мне, это самые, что ни на есть логические -И- и -ИЛИ-

Цитата:

Цитата Elven
абейте на ошибки, если они таки будут - вот вам || и радуйтесь этому как хотите. Ну а если ошибки нам неинтересны то и тем более && »

это вряд ли...
https://docs.microsoft.com/en-us/pow...or-interaction
если исключение слева, то правую часть фиг получим..., что неверно в случае ||

Foreigner 13-05-2021 19:50 2957791

Цитата:

Цитата YuS_2
если исключение слева, то правую часть фиг получим..., что неверно в случае || »

Код:

> $ErrorActionPreference = 'SilentlyContinue'
 > 1/0 && $true || $false
False
 > 0/1 && $true || $false
0
True


YuS_2 13-05-2021 22:31 2957810

Цитата:

Цитата Foreigner
$ErrorActionPreference = 'SilentlyContinue' »

А это вроде, как бы и не при чем? :)
В таком варианте вообще не будет прерывающих исключений...

Foreigner 13-05-2021 23:42 2957815

Цитата:

Цитата YuS_2
А это вроде, как бы и не при чем? »

Это чтобы подавить вывод ошибки.

YuS_2 14-05-2021 07:53 2957835

Цитата:

Цитата Foreigner
Это чтобы подавить вывод ошибки. »

Да, это понятно... но:
Подавляя вывод ошибок при возникновении непрерывающих исключений, можем получить неожиданные результаты при разработке скрипта в целом. Можно, конечно, уповать на свою память и думать, что ошибки мы нигде не совершим, но... мне кажется, что это несколько самонадеянно. :)
Да, можно, в каждом командлете переопределять действие этой переменной параметром erroraction, но все эти действия точно нужны, для использования этих синтетических И и ИЛИ? До powershell 7.0 как-то ведь обходились без них...

Foreigner 14-05-2021 09:02 2957839

Цитата:

Цитата YuS_2
До powershell 7.0 как-то ведь обходились без них... »

Я и сейчас не прибегаю к такой конструкции. В основном:

Код:

$ErrorActionPreference = 'Stop'

Try{}
Catch{}
Finally {} # редко

Главным образом при веб-запросах, например при обновлении FAR.

Elven 14-05-2021 10:15 2957849

Цитата:

Цитата YuS_2
Как по мне, это самые, что ни на есть логические -И- и -ИЛИ- »

нет. или по крайней мере не совсем. даже в bash или cmd/bat это не "И" и "ИЛИ", хоть их так и называют.

Цитата:

Цитата Foreigner
Try{}
Catch{}
Finally {} »

кстати поведение || в try может стать еще более неожиданным чем мне до этого казалось.
Вот здесь всё банально и логично:
Код:

Get-ChildItem nonexistfile || $true

Get-ChildItem: Cannot find path '/path/nonexistfile' because it does not exist.
True


1/0 || $true                     

RuntimeException: Attempted to divide by zero.
True

Просим возвращать true если имели ошибку - такое и получаем.
А теперь заворачиваем в try-catch:
c Get-Childitem получаем ожидаемый результат
Код:

try {
  Get-ChildItem nonexistfile || $true
}
catch {
  Write-Error "$?"
}

Cannot find path '/path/nonexistfile' because it does not exist.

True

сиречь True, а вот с 1/0...

Код:

try {
  1/0 || $true
}
catch {
  Write-Error "$?"
}

Write-Error: False

внезапно вываливаемся в catch.
Вот реально!

YuS_2 14-05-2021 10:21 2957852

Цитата:

Цитата Foreigner
Я и сейчас не прибегаю к такой конструкции. »

Ну, вряд ли, эта конструкция предназначена для замены try-catch-finally, она скорее замена условному блоку, т.е. упрощение записи, а существующие -and и -or, выдают не результат выполнения операторов и их операндов, а булевый... скажем:
Код:

$(ps) -and $(write-output test)
получим True, в отличие от:
Код:

$(ps) && $(write-output test)
и до версии 7.0, подобное выражение, нам пришлось бы записать так:
Код:

ps;if($?){write-output test}
т.е. по сути, вместо && и ||, это соответственно:
Код:

function test-command ($a){return $a}
# && правый будет выполнен только если выполнен левый
test-command '1'; if ($?) {test-command '2'}
# || если левый операнд выполнен
test-command '1'; if (!$?) {test-command '2'}
# || если левый операнд не выполнен, выполняем правый
write-error 'error'; if (!$?) {test-command '2'}

Цитата:

Цитата Elven
нет. »

Да, только результат будет не булевым, а именно то, что выполняет левый или правый операнд, всё просто, см. выше...

Цитата:

Цитата Elven
даже в bash или cmd/bat это не "И" и "ИЛИ", хоть их так и называют. »

там, как раз, полные аналоги этих введеных операторов в ps 7.0

Foreigner 14-05-2021 10:36 2957857

Цитата:

Цитата Elven
А теперь заворачиваем в try-catch »

На мой взгляд try-catch для этого не предназначен, его задача отловить ошибку, во всяком случае я его применяю в этом контексте -- отловить - вывести ошибку - прервать скрипт.

Код:

Try { $null = dir fakedir -ea 'stop' }
Catch { "fakedir не существует"; return }

"fakedir существует, продолжаем"


YuS_2 14-05-2021 10:42 2957858

Вложений: 1
Цитата:

Цитата Elven
внезапно вываливаемся в catch. »

хмм, а у меня так:
Файл 164523

Elven 14-05-2021 10:44 2957861

YuS_2, не тот кусок кода скопировал, мой косяк.
Код:

try {
  1/0 || $true
}
catch {
  Write-Error "$?"
}

Write-Error: False

Цитата:

Цитата Foreigner
его задача отловить ошибку, »

так и есть, но согласно логике описанной у ms строка
Код:

  1/0 || $true
вроде как не содержит ошибки (точнее содержит, но превращает ее все равно в true), т.о. в catch вываливать не должно, но вываливается.

Foreigner 14-05-2021 11:03 2957867

Цитата:

Цитата Elven
точнее содержит, но превращает ее все равно в true »

Try ее и отлавливает, оно не руководствуется конечным результатом ($true или $false не важны), а лишь отлавливает ошибку:

Код:

try {$true} # замените на $false, потом на 1/0
catch {'error'; return }

'not an error'


Elven 14-05-2021 11:09 2957870

Цитата:

Цитата Foreigner
лишь отлавливает ошибку»

Значит отлавливает ее по-разному, иначе почему точно так же содержащая ошибку
Код:

  Get-ChildItem nonexistfile || $true
возвращает True и в catch не вываливается?

Foreigner 14-05-2021 11:17 2957873

Цитата:

Цитата Elven
возвращает True и в catch не вываливается? »

Потому, что ее надо прерывать:
Код:

Get-ChildItem nonexistfile -ea 1 || $true
$ErrorActionPreference = 'stop'; 1/0 || $true


Elven 14-05-2021 11:25 2957878

Не объясняет поведения try-catch. Разумеется если дергать стоп при ошибке, то так оно и будет, но вопрос не в том как заставить пош делать так как нужно, а понять как же он вообще работает в данном случае, при находящемся $ErrorActionPreference в дефолтном Continue.

YuS_2 14-05-2021 11:26 2957879

Цитата:

Цитата Elven
не тот кусок кода скопировал, мой косяк. »

угу, понятно. Ну, что тут сказать, говорю же, синтетически внедренные операторы и видимо, их до конечного результата толком не отладили...
И кстати, именно этот момент описали в документации, я же ссылку выше приводил именно по этому поводу. Прерывающее исключение, прекращает работу операторов && и ||, т.е. завершает их работу и выдает результат только самого исключения.

Цитата:

Цитата Elven
Значит отлавливает ее по-разному, иначе почему точно так же содержащая ошибку
возвращает True и в catch не вываливается?
»

конечно, по-разному. try-catch-finally не ловит непрерывающие исключения.
То бишь, чтобы всё было в одинаковых условиях, должно быть так:
Код:

try {
    Get-ChildItem nonexistfile -ea 1|| $true
} catch {
    Write-Error "$?"
}


Elven 14-05-2021 11:59 2957890

ок, если уровнять обе строки посредством $ErrorActionPreference = 'Stop', значит вроде как они рАвно должны отработать и при $ErrorActionPreference = 'Continue'.

YuS_2 14-05-2021 12:17 2957898

Цитата:

Цитата Elven
если уровнять обе строки посредством $ErrorActionPreference = 'Stop', значит вроде как они рАвно должны отработать и при $ErrorActionPreference = 'Continue'. »

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


Время: 01:48.

Время: 01:48.
© OSzone.net 2001-