Tag Info

Hot answers tagged

24

You can use the R programming language. Here is a quick and dirty R script: #! /usr/bin/env Rscript d<-scan("stdin", quiet=TRUE) cat(min(d), max(d), median(d), mean(d), sep="\n") Note the "stdin" which is a special filename to read from stdin. Now you can redirect your data over stdin to the R script: $ cat datafile 1 2 4 $ ./mmmm.r < datafile 1 ...


21

There is already a command for this: seq 100 104 will print these numbers on separate lines: 100 101 102 103 104 So just direct this output into a file: seq 100 104 > my_file.txt and seq 100 2 104 will print in increments of two, namely: 100, 102, 104


18

Prefix the first number with a 0 to force each term to have the same width. $ echo {08..10} 08 09 10 From the bash man page section on Brace Expansion: Supplied integers may be prefixed with 0 to force each term to have the same width. When either x or y begins with a zero, the shell attempts to force all generated terms to contain the same ...


17

You can use the arithmetic expansion instead. echo "$(( 3 * ( 2 + 1 ) ))" 9 In my personal opinion, this looks a bit nicer than using expr. From man bash Arithmetic Expansion Arithmetic expansion allows the evaluation of an arithmetic expression and the substitution of the result. The format for arithmetic expansion is: ...


16

I actually keep a little awk program around to give the sum, data count, minimum datum, maximum datum, mean and median of a single column of numeric data: #!/bin/sh sort -n | awk 'BEGIN{c=0;sum=0;}\ /^[^#]/{a[c++]=$1;sum+=$1;}\ END{ave=sum/c;\ if((c%2)==1){median=a[int(c/2)];}\ else{median=(a[c/2]+a[c/2-1])/2;}\ print ...


16

Another way to use let bash builtin: $ let a="3 * (2 + 1)" $ printf '%s\n' "$a" 9 Note As @Stéphane Chazelas pointed out, in bash you should use ((...)) to do arithmetic over expr or let for legibility. For portability, use $((...)) like @Bernhard answer.


15

From the bash man page: ((expression)) The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expres- sion is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression". And further: ...


14

== is a bash-specific alias for =, which performs a string (lexical) comparison instead of a numeric comparison. (It's backwards from Perl: the word-style operators are numeric, the symbolic ones lexical.)


14

Bash does not understand floating point arithmetic. It treats numbers containing a decimal point as strings. Use awk or bc instead. #!/bin/bash min=12.45 val=10.35 if [ 1 -eq "$(echo "${val} < ${min}" | bc)" ] then min=${val} fi echo "$min" If you intend to do a lot of math operations, it's probably better to rely on python or perl.


14

I have a handy bash function called calc: calc () { bc -l <<< "$@" } Example usage: $ calc 65320/670 97.49253731343283582089 $ calc 65320*670 43764400 You can change this to suit yourself. For example: divide() { bc -l <<< "$1/$2" } Note: <<< is a here string which is fed into the stdin of bc. You don't need to ...


12

Your arithmetic evaluation syntax is wrong. Use any of the following (the first is extremely portable but slow, the second is POSIX and portable except to the Bourne shell and earlier versions of the Almquist shell, the last three require ksh, bash or zsh): a=`expr "$a" + "$num"` a=$(($a+$num)) ((a=a+num)) let a=a+num ((a+=num)) Or you can just skip ...


11

Min, max and average are pretty easy to get with awk: % echo -e '6\n2\n4\n3\n1' | awk 'NR == 1 { max=$1; min=$1; sum=0 } { if ($1>max) max=$1; if ($1<min) min=$1; sum+=$1;} END {printf "Min: %d\tMax: %d\tAverage: %f\n", min, max, sum/NR}' Min: 1 Max: 6 Average: 3,200000 Calculating median is a bit more tricky, since you need to sort numbers ...


11

From help let: Exit Status: If the last ARG evaluates to 0, let returns 1; let returns 0 otherwise.. Since var++ is post-increment, I guess the last argument does evaluate to zero. Subtle... A perhaps clearer illustration: $ let x=-1 ; echo x=$x \$?=$? x=-1 $?=0 $ let x=0 ; echo x=$x \$?=$? x=0 $?=1 $ let x=1 ; echo x=$x \$?=$? x=1 $?=0 $ let x=2 ; echo ...


11

In your case, you can simply disable zero padding by append - after % in the format string of date: %-H By default, date pads numeric fields with zeroes. The following optional flags may follow '%': - (hyphen) do not pad the field _ (underscore) pad with spaces 0 (zero) pad with zeros ^ use upper case if possible # use opposite case if ...


11

No need for bash, plain sh will do as well: #! /bin/sh - IFS=+; echo "$(($*))" $* in POSIX shells, expands to the list of positional parameters (in this case, the arguments to the script) separated by the first character of $IFS (or space if $IFS is unset or nothing if $IFS is empty). $((...)) is the shell internal arithmetic expansion operator (note ...


10

h=09; m=30;(( tot = 10#$h * 60 + 10#$m )); echo $tot The number before the # is the radix (or base) The number after the # must be valid for the radix The output is always decimal You can use a radix of 2 thru 64 (in GNU bash 4.1.5) As noted by enzoyib, the old alternative of $[expression] is depricated, so it is beter to use the POSIX compliant ...


10

You can use package num-utils for simple manipulations... For more serious maths, see this link... It describes several options, eg. R / Rscript (GNU R statistical computation and graphics system) octave (mostly Matlab compatible) bc (The GNU bc arbitrary precision calculator language) An example of numprocess echo "123.456" | numprocess ...


10

It's fairly straightforward to do the conversion from binary in pure bash (printf is a builtin): Binary to decimal $ echo "$((2#101010101))" 341 Binary to hexadecimal $ printf '%x\n' "$((2#101010101))" 155 Going back to binary using bash alone is somewhat more complex, so I suggest you see the other answers for solutions to that.


10

The man page of bash says: ! ~ logical and bitwise negation Signed numbers are usually stored in Two's complement representation: ... -4 = 1100 -3 = 1101 -2 = 1110 -1 = 1111 0 = 0000 1 = 0001 2 = 0010 3 = 0011 ... This means if you take a number like 2 it is bitwise interpreted as 0010. After bitwise negation this becomes 1101, which is the ...


10

Use parenthesis with quotes: expr 3 '*' '(' 2 '+' 1 ')' 9 The quotes prevent bash from interpreting the parenthesis as bash syntax.


10

There's no reason to be using expr for arithmetic in modern shells. POSIX defines the $((...)) expansion operator. So you can use that in all POSIX compliant shells (the sh of all modern Unix-likes, dash, bash, yash, mksh, zsh, posh, ksh...). a=$(( 3 * (2 + 1) )) a=$((3*(2+1))) ksh also introduced a let builtin which is passed the same kind of arithmetic ...


9

Actually you can set some attributes on variables using the declare (or the old typeset) builtin. declare -i var1 var2 will set integer attribute on those variables. After that assignments which attempt to set non-integer values to those variables will raise error. But your problem is with the syntax. When using a variable's value you have to prefix its ...


8

So between 2^63 and 2^64-1, you get negative integers showing you how far off from ULONG_MAX you are. No. How do you figure that? By your own example, the max is: > max=$((2**63 - 1)); echo $max 9223372036854775807 If "overflow" meant "you get negative integers showing you how far off from ULONG_MAX you are", then if we add one to that, shouldn't ...


8

Try xargs -n2 < file | while read x y; do ((X+=x*y)); echo $X; done xargs -n2: groups numbers in pairs read x y: store first and second number in variables x and y ((...)) is just a arithmetic evaluation in bash You will see on the screen how sum is growing.


8

In bash, numbers with leading zeros are considered as octal. You can use: next_number=$(printf %06d "$((10#$current_number + 1))") To tell bash to consider it as decimal. See also: $ printf 'A%06d\n' {5..12} A000005 A000006 A000007 A000008 A000009 A000010 A000011 A000012 Or: $ printf '%s\n' {A..C}{00008..00012} A00008 A00009 A00010 A00011 A00012 ...


8

The problem is in cases where the content of $x has not been sanitized and contains data that could potentially be under the control of an attacker in cases that shell code may end up being used in a privilege escalation context (for instance a script invoked by a setuid application, a sudoers script or used to process off-the-network data (CGI, DHCP ...


7

Linux ships with the seq command which does exactly that. If you don't have the seq command, it's an easy one-liner: i=100; while [ $i -le 104 ]; do echo $i; i=$((i+1)); done >b.txt or in ksh/bash/zsh for ((i=100; i<=104; i++)); do echo $i; done >b.txt or in zsh print -l {100..104} >b.txt


7

The substring inside the ` ` must be a valid command itself: rownum=`echo $nextnum+1 | bc` But is preferable to use $( ) instead of ` `: rownum=$(echo $nextnum+1 | bc) But there is no need for bc, the shell is able to do integer arithmetic: rownum=$((nextnum+1)) Or even simpler in bash and ksh: ((rownum=nextnum+1))


7

A non-looping variant: { printf %d+ "$@"; echo 0; } | bc Example Put the above in a script file, sum. #!/bin/bash { printf %d+ "$@"; echo 0; } | bc Run it like so: $ ./sum 4 4 $ ./sum 4 4 5 13


7

To create the table with a single call to awk: $ awk 'FNR==NR{s+=$2;next;} {printf "%s\t%s\t%s%%\n",$1,$2,100*$2/s}' data data foo 10 10% bar 20 20% oof 50 50% rab 20 20% How it works The file data is provided as an argument to awk twice. Consequently, it will be read twice, the first time to get the total, which is ...



Only top voted, non community-wiki answers of a minimum length are eligible