Met expr, $ (()), (())

In shell-script kunnen we expr $a*$b vervangen door $(($a+$b)).

Maar waarom niet alleen met (($a+$b)), want in elke bron staat geschreven dat (()) bedoeld is voor de berekening van gehele getallen.

Dus we gebruiken $(()) als er variabelen zijn in plaats van gehele getallen, nietwaar? En wat moeten we gebruiken in plaats van $(()) wanneer variabelen zwevende waarden kunnen ontvangen?

Opmerkingen

Antwoord

  1. Voor rekenkunde is expr archaïsch. Gebruik het niet. *

  2. $((...)) en ((...)) lijken erg op elkaar. Beide doen alleen berekeningen met gehele getallen. Het verschil is dat $((...)) het resultaat van de berekening retourneert en ((...)) niet. Dus $((...)) is handig in echo statements:

    $ a=2; b=3; echo $((a*b)) 6 

    ((...)) is handig als u een variabele wilt toewijzen of een afsluitcode wilt instellen:

    $ a=3; b=3; ((a==b)) && echo yes yes 
  3. Als u zwevend wilt puntberekeningen, gebruik bc of awk:

    $ echo "4.7/3.14" | bc -l 1.49681528662420382165 $ awk "BEGIN{print 4.7/3.14}" 1.49682 

* Even terzijde: expr blijft handig voor het afhandelen van tekenreeksen wanneer klodders niet goed genoeg zijn en een POSIX-methode nodig is om reguliere expressies af te handelen.

Opmerkingen

  • Als expr archaïsch is, wat moeten we dan gebruiken in plaats van expr-tekst: '. * '
  • Als s een shellvariabele is, is de lengte ${#s}
  • $ {#} betekent een aantal argumenten en $ (# s} betekent een aantal karakters van een variabele?
  • Ja. Dat ' klopt.
  • @Stranger Veel gebruik van expr STRING : REGEX kan worden geschreven als case STRING in PATTERN). expr is alleen nuttig als REGEX ' niet kan worden uitgedrukt met shell-jokertekens.

Answer

expr is oud, maar het heeft een beperkt nut dat ik kan bedenken. Stel dat u in een string wilt zoeken. Als je POSIX met grep wilt blijven, moet je een pipe gebruiken:

if echo november | grep nov then : do something fi 

expr kan dit doen zonder een pipe:

if expr november : nov then : do something fi 

de enige catch is expr werkt met verankerde strings, dus als je wilt matchen na het begin, moet je de REGEXP wijzigen:

if expr november : ".*ber" then : do something fi 

Met betrekking tot (( )), deze constructie is niet POSIX , dus moet worden vermeden.

Met betrekking tot $(( )) hoeft u het dollarteken niet op te nemen:

$ fo=1 $ go=2 $ echo $((fo + go)) 3 

Opmerkingen

  • Veel gebruik van expr STRING : REGEX kan worden geschreven als case STRING in PATTERN). expr is alleen nuttig als REGEX ' niet kan worden uitgedrukt met shell-jokertekens.

Answer

Het lijkt erop dat de volgende programmas min of meer hetzelfde doen en niet echt verschillen. Maar dat is niet waar.

#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )), do s=$((s+1)) echo $s 

Dit is de juiste manier om dit te implementeren. De uitdrukking s + 1 wordt geëvalueerd door de shell en kan worden toegewezen aan een variabele.

#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )), do s=`expr $s+1` echo $s 

Hier zal de uitdrukking worden berekend door het programma expr, dat” geen shell is ingebouwd, maar een extern Unix-programma. Dus in plaats van simpelweg 1 en s toe te voegen, moet een programma worden gestart en moet de uitvoer ervan worden gelezen en naar de variabele worden geschreven. Het starten van een programma vergt veel middelen en veel tijd. En dit programma wordt 1000000 keer uitgevoerd. Het programma zal dus veel langzamer zijn dan het vorige. Desalniettemin werkt de code correct.

#!/bin/bash -e s=-1000 for (( i=0; i<1000000; i++ )), do ((s=s+1)) echo $s 

Als de vlag -e niet is ingesteld, zal het programma ook correct werken. Maar als -e is ingesteld wanneer s = -1 en ((s = s + 1)) wordt berekend. De uitdrukking s = s + 1 resulteert in 0 en de afsluitcode van ((0)) is> 0, wat door de shell wordt geïnterpreteerd als een fout en de shell verlaat het programma.

De reden om de vlag -e in te stellen is dat dit de eenvoudigste manier is om fouten te verwerken: stop als er een fout optreedt.

Geef een reactie

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