This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
commands:builtin:let [2011/01/13 17:39]
thebonsai fixed internal link
commands:builtin:let [2015/11/16 04:19] (current)
thebonsai [The let builtin]
Line 1: Line 1:
-====== The let builtin ======+====== The let builtin ​command ​======
 ===== Synopsis ===== ===== Synopsis =====
 <​code>​ <​code>​
-let <​EXPRESSION>​+let arg [arg ...]
 </​code>​ </​code>​
 ===== Description ===== ===== Description =====
-The ''​let''​ builtin command evaluates ​the [[syntax:​arith_expr | arithmetic expression]] ​''<​EXPRESSION>'' ​and returns the exit codes +The ''​let''​ builtin command evaluates ​each supplied word from left to right as an [[syntax:​arith_expr | arithmetic expression]] and returns ​an exit code according to the truth value of the rightmost expression. 
-  * 0 (TRUE) when ''​<​EXPRESSION>​''​ evaluated to not 0 (arithmetic "​true"​) +  * 0 (TRUE) when ''​arg''​ evaluated to not 0 (arithmetic "​true"​) 
-  * 1 (FALSE) when ''​<​EXPRESSION>​''​ evaluated to 0 (arithmetic "​false"​) +  * 1 (FALSE) when ''​arg''​ evaluated to 0 (arithmetic "​false"​) 
-For this return code mapping, please see [[syntax:​arith_expr#​arithmetic_expressions_and_return_codes | this section]].+For this return code mapping, please see [[syntax:​arith_expr#​arithmetic_expressions_and_return_codes | this section]]. They work in the same way as ''<​nowiki>​((</​nowiki>''​. 
 +===== Examples ===== 
 +''​let''​ is very similar to [[syntax:​ccmd:​arithmetic_eval | ((]] - the only difference being ''​let''​ is a builtin (simple command), and ''<​nowiki>​((</​nowiki>''​ is a compound command. The arguments to ''​let''​ are therefore subject to all the same expansions and substitutions as any other simple command - requiring proper quoting and escaping - whereas the contents of ''<​nowiki>​((</​nowiki>''​ aren't subject to [[syntax:​expansion:​wordsplit | word-splitting]] or [[syntax:​expansion:​globs | pathname expansion]] (almost never desirable for arithmetic). For this reason, **the [[syntax:​ccmd:​arithmetic_eval | arithmetic compound command]] should generally be preferred over ''​let''​**.
-The form (note the quoting!) 
 <​code>​ <​code>​
-let "<​EXPRESSION>​"+let 'b = a' ​"(a += 3) + $((a = 1)), b++" 
 +$ echo "$a - $b - $?" 
 +4 - 2 - 0
 </​code>​ </​code>​
-is identical ​to the [[syntax:​ccmd:​arithmetic_eval | arithmetic evaluation compound command]] ​(except the exit code)+Is equivalent ​to the [[syntax:​ccmd:​arithmetic_eval | arithmetic evaluation compound command]]:
 <​code>​ <​code>​
-(( <​EXPRESSION> ​))+(( b = a, (a += 3) + $((a = 1)), b++ )) 
 +$ echo "$a - $b - $?" 
 +4 - 2 - 0
 </​code>​ </​code>​
-This way should be preferred.+<WRAP info> 
 +Remember that inside arithmetic evaluation contexts, all other expansions are processed as usual (from left-to-right),​ and the resulting text is evaluated as an arithmetic expression. Arithmetic already has a way to control precedence using parentheses,​ so it's very rare to need to nest arithmetic expansions within one another. It's used above only to illustrate how this precedence works. 
-===== Examples ===== +Unlike ​''​<​nowiki>​((</​nowiki>​''​, being a simple ​command ​''​let''​ has its own environment. In Bash, built-ins that can set variables process any arithmetic under their own environment,​ which makes the variable effectively "​local"​ to the builtin unless the variable ​is also set or modified ​by the builtinThis differs in other shells, such as ksh93, where environment assignments to regular builtins are always local even if the variable ​is modified by the builtin.
- +
- +
-===== Portability considerations ===== +
-The ''​let''​ command is not specified ​by POSIX(r)The standard equivalent ​is:+
 <​code>​ <​code>​
-"$(( <​EXPRESSION>​ ))" -ne 0 ]+ ~ $ ( y=1+1 let x=y; declare -p x y ) 
 +declare -- x="2" 
 +bash: declare: y: not found 
 + ​~ ​$ ( y=1+1 let x=y++; declare -p x y ) 
 +declare -- x="2" 
 +declare ​-- y="​3"​
 </​code>​ </​code>​
-The quotes around ​the [[syntax:​arith_expr | arithmetic expansion]] are only necessary with bash and AT&T versions ​of kshother standard shells such as ashpdksh or zsh derivatives don't have that bug/misfeature.+This can be useful in certain situations where a temporary variable is needed. 
 +===== Portability considerations ===== 
 +  * the ''​let''​ command is not specified by POSIX(r). ​The portable alternative is: <​code>​[ "$(( <​EXPRESSION>​ ))" -ne 0 ]</​code>​. To make portable scripts simpler and cleaner, ''​let''​ can be defined as: <​code>​ 
 +# POSIX 
 +let() { 
 +    IFS=, command eval test '​$(($*))'​ -ne 0 
 +</​code>​ Aside from differences in supported arithmetic features, this should be identical to the Bash/Ksh ''​let''​. 
 +  * It seems to be a common misunderstanding that ''​let''​ has some legacy purpose. Both ''​let''​ and [[syntax/​ccmd/​arithmetic_eval | ((...))]] were ksh88 features and almost identical in terms of portability as everything that inherited one also tended to get the other. Don't choose ''​let''​ over ''​((''​ expecting it to work in more places. 
 +  * [[http://​pubs.opengroup.org/​onlinepubs/​9699919799/​utilities/​expr.html#​tag_20_42 | expr(1)]] is a command one is likely to come across sooner or later. While it is more "​standard"​ than ''​let'',​ the above should always be preferred. Both [[syntax:​arith_expr | arithmetic expansion]]s and the ''​[''​ test operator ​are specified by POSIX(r) ​and satisfy almost all of expr's use-cases. Unlike ''​let''​''​expr''​ cannot assign directly to bash variables but instead returns a result on stdout. ''​expr''​ takes each operator it recognizes ​as a separate word and then concatenates them into a single expression that's evaluated according to it's own rules (which differ from shell arithmetic). ''​let''​ parses each word it recieves on its own and evaluates it as an expression without generating any output other than a return code. 
 +  * For unknown reasons, ''​let''​ is one of the Bash commands with special parsing for arguments formatted like compound array assignments. See: [[commands/builtin/​eval#​portability_considerations | eval]] for details. There are no known practical uses for this. Parentheses are treated as grouping operators and compound assignment is not possible by arithmetic expressions.
 ===== See also ===== ===== See also =====
Line 43: Line 65:
   * Internal: [[syntax:​arith_expr | arithmetic expressions]]   * Internal: [[syntax:​arith_expr | arithmetic expressions]]
   * Internal: [[syntax:​ccmd:​arithmetic_eval | arithmetic evaluation compound command]]   * Internal: [[syntax:​ccmd:​arithmetic_eval | arithmetic evaluation compound command]]