So I'm trying to create a random number limit the range from 1 to 10. There is a slightly different syntax between the two and I don't know if there any difference between those.
$(($RANDOM % 10 +1))
I tried this and it's working fine.
$(( ( RANDOM % 10 ) + 1 )). Including an extra () between RANDOM % 10 and +1 seems to work the same as the code above. But it has only one $ instead of 2.
Nothing. % has higher precedence (the same as *) than +, so the unparenthesized version is equivalent to the explicitly parenthesized one.
I originally missed that the second one also used RANDOM instead of $RANDOM. In an arithmetic context, a string is treated as an identifier, and is (recursively) expanded until you get an integer. If at any point the string is not a defined parameter, the value 0 is used instead. For example:
$ foo=bar
$ bar=6
$ echo $((bar))
6
$ echo $((foo))
6
In the last case, $foo expands to bar, which expands to 6.
IMO, it's better to use the explicit expansion. If the parameter isn't set due to a typo, you'll get an explicit error
$ foo=6
$ echo $((10 + $fo))
bash: 10 + : syntax error: operand expected (error token is "+ ")
rather than a silent "success" that might not be intended
$ echo $((10 + fo))
10 # ?? Why not 16?
Related
I'm trying to batch modify some images using a bash script, and to print out the progress. It looks to me like bash is interpreting the increment to counter as a command and is giving the following error:
augment_data.sh: line 20: 0: command not found
Here is the code:
for file in *.jpg
do
convert $file -rotate 90 rotated_"$file"
((counter++))
if $((counter % 10 == 0)); then
echo "Rotated $counter files out of $num_files"
fi
done
with line 20 being the one with the counter increment operation.
How can I fix this so that I don't get the error message?
In an arithmetic substitution, the result of an arithmetic operation is substituted in the position of the operation itself.
In this case, $(( 1 == 0 )) has an arithmetic result of 0, and $(( 1 == 1 )) has a result of 1.
Thus, if you use $(( ... )), then this 0 or 1 is substituted in that position, and so gets run as a command. Since you don't have commands named 0 or 1 (probably), either of these will result in a command not found error.
If you use (( ... )), then the arithmetic result directly sets return value, but no expansion takes place.
I have never seen the following shell script syntax:
cpu_now=($(head -n 1 /proc/stat))
cpu_sum="${cpu_now[#]:1}"
cpu_sum=$((${cpu_sum// /+}))
Can anyone explain what the ${cpu_sum// /+} mean here?
It means the same as $cpu_sum, but with all occurrences of (a space) being replaced by +. (See ยง3.5.3 "Shell Parameter Expansion" in the Bash Reference Manual.)
cpu_sum=$((${cpu_sum// /+}))
It is actually 2 step operation:
First all the spaces are being replaced by + in ${cpu_sum// /+}
Then using $((...)) arithmetic addition is being performed for adding all the numbers in $cpu_sum variable to get you aggregate sum.
Example:
# sample value of cpu_sum
cpu_sum="3222 0 7526 168868219 1025 1 357 0 0 0"
# all spaced replaced by +
echo ${cpu_sum// /+}
3222+0+7526+168868219+1025+1+357+0+0+0
# summing up al the values and getting aggregate total
echo $((${cpu_sum// /+}))
168880350
I know c shell is very unfriendly but I am stuck with it. So can someone help me with this should-be-a-easy syntax error ? I would like to use modulus operator in c shell. So the command is like this and it keeps giving me syntax error of expr command.
set aVAr =`expr $number * 2 % $frequency`
I found out I can type "expr 6 % 5 " and "expr 3 * 2". However, I can not use command as "expr 3 * 2 % 5 ". What's wrong with it ? I think CSH should be table to take three operands at the same time ? Thank you very much,
expr is a command, not part of csh. You must escape the * to prevent csh from trying to expand it, as in
set aVAr =`expr $number \* 2 % $frequency`
Is there a way to find the size(memory used) of shell variable from command line, without using C ?
This tells you how many characters are in the value of a scalar variable named "var":
echo ${#var}
This tells you the number of elements in an array named "array":
echo ${#array[#]}
This tells you the number of characters in an element of an array:
echo ${#array[3]}
If you try to get the size of an array and you leave out the [#] index, you get the length of element 0:
$ array=(1 22 333 4444)
$ echo ${#array}
1
$ echo ${#array[#]}
4
$ echo ${#array[2]}
3
If you want the total length of all elements of an array, you could iterate over the array and add them up, you could use IFS and some steps similar to those below, or you could:
$ tmp="${array[*]}"
$ echo $(( ${#tmp} - ${#array[#]} + 1 ))
10
Beware of using the number of elements in an array as the index of the last element since Bash supports sparse arrays:
$ array=(1 22 333 4444 55555)
$ echo ${#array[#]}
5
$ array[9]=999999999
$ echo ${#array[#]}
6
$ echo ${array[${#array[#]} - 1]} # same as echo ${array[6 - 1]}
$ # only a newline is echoed since element 5 is empty (only if "nounset" option* is not set (default in most cases))
$ # when "nounset" option is set (possibly using command "set -u") then bash will print such error:
$ # bash: array[${#array[#]} - 1]: unbound variable
$ unset "array[1]" # always quote array elements when you unset them
$ echo ${#array[#]}
5
$ echo ${array[${#array[#]} - 1]} # same as echo ${array[5 - 1]}
55555
That was obviously not the last element. To get the last element:
$ echo ${array[#]: -1} # note the space before the minus sign
999999999
Note that in the upcoming Bash 4.2, you can do echo ${array[-1]} to get the last element. In versions prior to 4.2, you get a bad subscript error for negative subscripts.
To get the index of the last element:
$ idx=(${!array[#]})
$ echo ${idx[#]: -1}
9
Then you can do:
$ last=${idx[#]: -1}
$ echo ${array[last]}
999999999
To iterate over a sparse array:
for idx in ${!array[#]}
do
something_with ${array[idx]}
done
* I recommend avoiding nounset
wc can tell you how many characters and bytes are in a variable, and bash itself can tell you how many elements are in an array. If what you're looking for is how large bash's internal structures are for holding a specific variable then I don't believe that's available anywhere.
$ foo=42
$ bar=(1 2 3 4)
$ echo -n "$foo" | wc -c -m
2 2
$ echo "${#bar[#]}"
4
For a scalar variable, ${#VAR} gives you the length in characters. In a unibyte locale, this is the length in bytes. The size in bytes is the length of the name in bytes, plus the length of the value in bytes, plus a constant overhead.
LC_ALL=C
name=VAR
size=$(($#name + $#VAR)) # plus a small overhead
If the variable is exported, the size is roughly double.
LC_ALL=C
name=VAR
size=$((($#name + $#VAR) * 2)) # plus a small overhead
For an array variable, you need to sum up the lengths (again, in bytes) of the elements, and add a constant overhead per element plus a constant overhead for the array.
LC_ALL=C
name=VAR
size=$(($#name)) # plus a small overhead
for key in "${!VAR[#]}"; do
size=$((size + ${#key} + ${#VAR[$key]})) # plus a small overhead
done
Here's a minimally tested function that computes the approximate size occupied by a variable. Arrays and exports are taken into account, but not special read-only variables such as $RANDOM. The sizes have been observed on bash 4.2, different versions may have different overheads. You may need to adjust the constants depending on your system types and malloc implementation.
_sizeof_pointer=4
_sizeof_int=4
_malloc_granularity=16
_malloc_overhead=16
## Usage: compute_size VAR
## Print the amount of memory (in bytes) used by VAR.
## The extra bytes used by the memory allocator are not taken into account.
add_size () {
local IFS="+" this extra
set $(($1 + _malloc_overhead))
_size=$((_size + $1))
set $(($1 % _malloc_granularity))
[[ $1 -eq 0 ]] || _size=$((_size + _malloc_granularity - $1))
}
compute_size () {
local LC_ALL=C _size=0 _key
if eval "[ -z \${$1+1} ]"; then echo 0; return; fi
add_size $((_sizeof_pointer*5 + _sizeof_int*2)) # constant overhead
add_size ${#1} # the name
case $(declare -p $1) in
declare\ -x*)
eval "add_size \${#$1}" # the value
eval "add_size \$((\${#1} + \${#$1} + 2))" # the export string
;;
declare\ -a*)
eval 'for _key in "${!'$1'[#]}"; do
add_size $_key
add_size ${#'$1'[$_key]}
add_size $((_sizeof_pointer*4))
done'
add_size $((_sizeof_pointer*2 + _sizeof_int*2))
add_size $((_sizeof_pointer*4))
;;
*)
eval "add_size \${#$1}" # the value
;;
esac
echo $_size
}
${#VAR}
tells you the length of the string VAR
Under windows, when I need to perform a basic calculations, I use a built-in calculator. Now I would like to find out what is the common way if you only have a shell.
Thanks
From this web page (for csh and derivatives, since you asked):
% # x = (354 - 128 + 52 * 5 / 3)
% echo Result is $x
Result is 174
and
% set y = (354 - 128 + 52 / 3)
% echo Result is $y
Result is 354 - 128 + 52 / 3
notice the different results.
Personally, I stick to /bin/sh and call awk or something (for maximal portability), or others have exhibited the bash approach.
You can use dc. Or bc.
There are many good solutions given here, but the 'classic' way to do arithmetic in the shell is with expr:
$ expr 1 + 1
2
expr has a sensible return value, so that it succeeds when the expression evaluates to a non-zero value allowing code (in a Bourne shell) like:
$ op="1 + 1"
$ if expr $op > /dev/null; then echo "$op is not zero"; fi
1 + 1 is not zero
or (if using a shell that supports arrays):
$ op=(8 \* 3)
$ if expr "${op[#]}" > /dev/null; then echo "${op[#]} is not zero"; fi
8 * 3 is not zero
Note that the if syntax in Bourne shells is completely different than in the csh family, so this is slightly less useful and you need to check against the value of #?.
Bash supports basic (integer only) arithmetic inside $(( )):
$ echo $(( 100 / 3 ))
33
$ myvar="56"
$ echo $(( $myvar + 12 ))
68
$ echo $(( $myvar - $myvar ))
0
$ myvar=$(( $myvar + 1 ))
$ echo $myvar
57
(example copied straight from the IBM link)
More in-depth discussion of bash arithmetic
And you can always use the python interpreter, it's normally included in linux distros.
http://docs.python.org/tutorial/introduction.html#using-python-as-a-calculator
$ python
Python 2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)]
Type "help", "copyright", "credits" or "license" for more information.
>>> 2+2
4
>>> # This is a comment
... 2+2
4
>>> 2+2 # and a comment on the same line as code
4
>>> (50-5*6)/4
5
>>> # Integer division returns the floor:
... 7/3
2
>>> 7/-3
-3
>>> # use float to get floating point results.
>>> 7/3.0
2.3333333333333335
The equal sign ('=') is used to assign a value to a variable. Afterwards, no result is displayed before the next interactive prompt:
>>> width = 20
>>> height = 5*9
>>> width * height
900
And of course there's the math module which should solve most of your calculator needs.
>>> import math
>>> math.pi
3.1415926535897931
>>> math.e
2.7182818284590451
>>> math.cos() # cosine
>>> math.sqrt()
>>> math.log()
>>> math.log10()
You can also use Perl easily where bc or expr are not powerful enough:
$ perl5.8 -e '$a=1+2; print "$a\n"'
3
Alternative option is to use the built in BC command