Booleaanse operatoren in bash-script begrijpen [duplicate]

Deze vraag heeft hier al antwoorden :

Antwoord

De variabele $phone_missing is een tekenreeks die false bevat. En een niet-lege string resulteert in true. Zie ook http://www.linuxintro.org/wiki/Babe#empty_strings

Reacties

  • Ah oké. Ik zou die variabele als booleaans hebben gedeclareerd (althans niet met het declare-woord) maar de ash-console heeft ' me niet laten staan. Ik wil ' ook geen Strings vergelijken. Hoe wordt dit correct gedaan?
  • stackoverflow.com/questions/2953646/… , maar pas op: deze man VOERT een stringvariabele UIT, en zowel false als true zijn unix-commandos.

Answer

Ik gebruik vaak “true” en “false” omdat het ook commandos zijn die alleen respectievelijk succes en mislukking teruggeven. Dan kun je

if "$phone_missing"; then ... 

Answer

Hier is een manier om te doen dit, met behoud van de waar / onwaar-waarden.

 phone_missing=false if [ "$phone_missing" != false ]; then echo "phone_missing is not "false" (but may be non-true, too)" fi if [ "$phone_missing" == true ]; then echo "phone_missing is true." fi  

De dubbele aanhalingstekens rond $phone_missing zijn ter bescherming tegen het geval waarin variabele phone_missing helemaal niet is gedefinieerd. Een ander algemeen idioom om hiertegen af te weren is [ x$phone_missing != xfalse ], maar de aanhalingstekens lijken mij natuurlijker.

De hint staat op de bash helppagina voor test:

 STRING True if string is not empty. ... ! EXPR True if expr is false. 

Dus in feite is [ $foo ] waar als $foo niet leeg is. Niet waar of niet waar, alleen niet leeg. [ ! $foo ] is waar als $ foo leeg of ongedefinieerd is.

Je zou altijd je code kunnen veranderen door phone_missing in te stellen op een niet -leeg waarde e, wat true aangeeft. Als phone_missing niet is ingesteld (of leeg – phone_missing=""), is het onwaar. Anders zou u de string-testoperatoren moeten gebruiken (= en !=).

Het andere kleine probleem is de opdracht. Je hebt het als $phone_missing=true, terwijl het phone_missing=true zou moeten zijn (geen dollarteken).

Sorry als dit het geval is een beetje dicht, het is omdat ik ben. Het is een lange dag geweest. 🙂

Antwoord

Andere antwoorden gaven je een oplossing, maar ik zal uitleggen wat er mis was met het oorspronkelijke denken.

Bash-variabelen hebben geen typen, dus er bestaat niet zoiets als een booleaanse variabele of waarde zoals true of false. In principe zijn alle bash-variabelen slechts strings.

Wanneer u een variabele / string in bash test zonder het type test op te geven (-n of -z), wordt standaard een -n -test (tekenreeks niet nul).

Dus [ "$var" ] is gelijk aan [ -n "$var" ]. Zolang $var minstens 1 teken bevat, werd geëvalueerd als waar.

Omdat je de uitdrukking negeerde, [ ! "$var" ] is gelijk aan [ ! -n "$var" ]. Dus als $var minstens 1 teken bevat, dan is de uitdrukking false.

Omdat false (wat gewoon a string) bevat 5 karakters, de uitdrukking is false. Als het niet uitmaakt welke string u phone_missing instelt op (true, 0, 1), zal de uitdrukking altijd false omdat is phone_missing niet nul is. De enige manier om het true te maken is phone_missing="" aangezien dat de lengte nul is.

Antwoord

Gebruik geen string voor booleaans. Gebruik integer.

Invoer:

val=1 ((val)) && echo "true" || echo "false" val=0 ((val)) && echo "true" || echo "false" 

Uitvoer:

true false 

Bron :

((expressie))

De uitdrukking wordt geëvalueerd volgens de regels die hieronder worden beschreven onder ARITMETISCHE EVALUATIE. Als de waarde van de uitdrukking niet nul is, is de retourstatus 0; anders is de retourstatus 1. Dit is exact gelijk aan let “expression”.

Antwoord

Ik zou dit hebben gedaan als een opmerking om James te steunen Ko maar had niet de vertegenwoordiger om commentaar te geven of publiekelijk te stemmen.

Het probleem hier is dat de haakjes [] de notatie zijn voor het uitvoeren van een vergelijkingstest, zoals waarde of gelijkheid van tekenreeksen.

String-waarheidsgetrouwheid in bash voor een lege string is "" (lege string) evalueert naar false (retourwaarde 1) en elke niet-lege string “false” “true “of” bob “s uw oom” evalueert naar waar (retourwaarde 0).

U kunt dit voor uzelf bewijzen met:

 if [ "foo" ]; then echo true is $?; else echo false is $?; fi 

De $? hierboven is een speciale variabele die de laatste exit-status van de opdrachten bevat (0 success, en elke> 0 voor foutcode) en zal true is 0. U kunt "foo" vervangen door wat u maar wilt en het resultaat is hetzelfde, behalve als u het vervangt door een lege tekenreeks "" of "", in welk geval het de else-voorwaarde evalueert en false is 1 uitvoert.

Bij gebruik van de [ ] tussen haakjes de interne instructie zoals! $ phone_missing wordt geëvalueerd en retourneert vervolgens een 0 voor true of 1 voor false voor de if contro l verklaring. Aangezien het haakje tekenreeks- en waardevergelijkingen evalueert, wordt $ phone_missing eerst uitgebreid naar de niet-lege tekenreeks “false” die wordt geëvalueerd door de [] als niet-lege tekenreeks (of true) en vervolgens de! keert het resultaat om, wat resulteert in de if-instructie die een false krijgt (of retourwaarde 1) en het slaat de voorwaardelijke body over die de else-instructie uitvoert, indien aanwezig.

Zoals James Ko zei, zou de notatie zijn om gewoon de variabele die uw “boolean” vasthoudt aan de if control-instructie. Let op dat in bash een boolean true en false in kleine letters moeten zijn, zoals in: bool_true = true bool_false = false In elk ander geval zal evalueren als strings en niet als boolean.

Dus als u uw voorbeeld en het antwoord van James Ko gebruikt, zou het zijn:

phone_missing=false echo "missing $phone_missing" if ! $phone_missing then echo "Lost phone at $readabletime" $phone_missing=true fi 

of zoals ik geef de voorkeur aan leesbaarheid (syntactisch hetzelfde en James Kos)

phone_missing=false echo "missing $phone_missing" if ( ! $phone_missing ); then echo "Lost phone at $readabletime" $phone_missing=true fi 

Andere antwoorden, zoals door Alexios, controleren letterlijk de inhoud van de tekenreeks. Zodat een van de volgende dingen zou resulteren in false:

phone_missing=false if [ "$phone_missing" != false ]; then echo "phone_missing is not "false" (but may be non-true, too)" fi if [ "$phone_missing" == true ]; then echo "phone_missing is not "false" (but may be non-true, too)" fi if [ "$phone_missing" == Bobs_your_uncle ]; then echo "phone_missing is not "false" (but may be non-true, too)" fi 

Answer

De juiste syntaxis is if ! $bool; then [statements]; fi.

Voorbeeld:

bool=false if ! $bool; then echo "This is correct!" fi if [ ! $bool ]; then echo "This is wrong!" fi 

Uitvoer: This is correct!

Reacties

  • Er zit een kern van waarheid in je antwoord, maar bij gebrek aan enige uitleg veroorzaakt het meer verwarring dan het oplost. Het is ook weinig meer dan een herhaling van een van de vorige antwoorden. Als je niet wilt dat je antwoord wordt verwijderd, leg dan uit waarom het juist is.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *