syntax:ccmd:c_for

# Differences

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

​TODO:​ Show some alternate usages involving functions and local variables for initialization.​ ===== Examples ===== ===== Examples ===== + ==== Simple counter ==== ==== Simple counter ==== A simple counter, the loop iterates 101 times ("​0"​ to "​100"​ are 101 numbers -> 101 runs!), and everytime the variable ''​x''​ is set to the current value. A simple counter, the loop iterates 101 times ("​0"​ to "​100"​ are 101 numbers -> 101 runs!), and everytime the variable ''​x''​ is set to the current value. - * it **initializes** ''​x = 0''​ + * It **initializes** ''​x = 0''​ - * before ​every iteration it **checks** if ''​x ​<= 100''​ + * Before ​every iteration it **checks** if ''​x ​≤ 100''​ - * after every iteration it **changes** ''​x++''​ + * After every iteration it **changes** ''​x++''​ <​code>​ <​code>​ Line 78: Line 85: ==== Stepping counter ==== ==== Stepping counter ==== - This is the very same counter (compare it to the simple counter example above), but the **change** that is made is a ''​x = x + 10''​. That means, it will count from 0 to 100, but with a **step of 10**. + + This is the very same counter (compare it to the simple counter example above), but the **change** that is made is a ''​x ​+= 10''​. That means, it will count from 0 to 100, but with a **step of 10**. <​code>​ <​code>​ - for ((x = 0 ; x <= 100 ; x = x + 10)); do + for ((x = 0 ; x <= 100 ; x += 10)); do echo "​Counter:​ \$x" echo "​Counter:​ \$x" done done Line 87: Line 95: ==== Bits analyzer ==== ==== Bits analyzer ==== - This is a bit more complex, but really just a little ​bit. + This example loops through the bit-values of a Byte, beginning from 128, ending at 1. If that bit is set in the ''​testbyte'',​ it prints "''​1''",​ else "''​0''"​ => it prints the binary representation of the ''​testbyte''​ value (8 bits). + <​code>​ + #​!/​usr/​bin/​env bash + # Example written for http://​wiki.bash-hackers.org/​syntax/​ccmd/​c_for#​bits_analyzer + # Based on TheBonsai'​s original. + + function toBin { + typeset m=\$1 n=2 x='​x[(n*=2)>​m]'​ + for ((x = x; n /= 2;)); do + printf %d \$(( m & n && 1)) + done + } + + function main { + [[ \$1 == +([0-9]) ]] || return + typeset result + if (( \$(ksh -c '​printf %..2d \$1' _ "​\$1"​) == ( result = \$(toBin "​\$1"​) ) )); then + printf '%s is %s in base 2!\n' "​\$1"​ "​\$result"​ + else + echo 'Oops, something went wrong with our calculation.' >&​2 + exit 1 + fi + } + + main "​\${1:​-123}"​ + + # vim: set fenc=utf-8 ff=unix ft=sh : + ​ - It loops through the bit-values of a Byte, beginning from 128, ending at 1. If that bit is set in the ''​testbyte'',​ it prints "''​1''",​ else "''​0''"​ => it prints the binary representation of the ''​testbyte''​ value (8 bits). +
<​code>​ <​code>​ testbyte=123 testbyte=123 - for (( n = 128 ; n >= 1 ; n = n / 2 )); do + for (( n = 128 ; n >= 1 ; n /= 2 )); do if (( testbyte & n )); then if (( testbyte & n )); then - ​echo -n "1" + ​printf %d 1 else else - ​echo -n "0" + ​printf %s 0 fi fi done done - echo # final linefeed + echo ​ + ​ + Why that one begins at 128 (highest value, on the left) and not 1 (lowest value, on the right)? It's easier to print from left to right... Why that one begins at 128 (highest value, on the left) and not 1 (lowest value, on the right)? It's easier to print from left to right... + We arrive at 128 for ''​n''​ through the recursive arithmetic expression stored in ''​x'',​ which calculates the next-greatest power of 2 after ''​m''​. To show that it works, we use ksh93 to double-check the answer, because it has a built-in feature for ''​printf''​ to print a representation of any number in an arbitrary base (up to 64). Very few languages have that ability built-in, even things like Python. + + ==== Up, down, up, down... ==== + + This counts up and down from ''​0''​ to ''​\${1:​-5}'',​ ''​\${2:​-4}''​ times, demonstrating more complicated arithmetic expressions with multiple variables. + + <​code>​ + for (( incr = 1, n=0, times = \${2:-4}, step = \${1:-5}; (n += incr) % step || (incr *= -1, --times);​));​ do + printf '​%*s\n'​ "​\$((n+1))"​ "​\$n"​ + done + ​ + <​code>​ ~ \$ bash <(xclip -o) + 1 + 2 + 3 + 4 + 5 + 4 + 3 + 2 + 1 + 0 + 1 + 2 + 3 + 4 + 5 + 4 + 3 + 2 + 1 + ​ ===== Portability considerations ===== ===== Portability considerations ===== + + * C-style for loops aren't POSIX. They are available in Bash, ksh93, and zsh. All 3 have essentially the same syntax and behavior. + * C-style for loops aren't available in mksh. + + ===== Bugs ===== + + * //Fixed in 4.3//. <​del>​There appears to be a bug as of Bash 4.2p10 in which command lists can't be distinguished from the for loop's arithmetic argument delimiter (both semicolons),​ so command substitutions within the C-style for loop expression can't contain more than one command.​ ===== See also ===== ===== See also =====
• syntax/ccmd/c_for.1286912785.txt