Showing posts with label arithmetic. Show all posts
Showing posts with label arithmetic. Show all posts

Thursday, November 20, 2008

Plain English Explanation Of An Awk Statement For Linux Or Unix

Hey There,

Today's post is going to be a follow-up to yesterday's post on convoluted column arithmetic in awk. I have a nasty habit of listing all my stuff as "beginner" material. Mostly this is because I try to write my material for the middle level to newer user of Unix, Linux, Perl, etc. I have absolutely no interest in picking apart the finer points of quantum mathematics or advanced concepts in programming or operating system design and implementation. I leave that for the academics. Besides, if I did go that route, I'd have to narrow the scope of this blog a "whole lot" ;)

Yesterday's post offered a number of cut-and-paste awk solutions to solving some seemingly difficult data massaging problems and, in my frantic struggle to keep my post under a thousand words, I cut some corners and simply framed the problem, following it with the solution. It's usually a good formula. I'll be the first to admit, though, that the examples were somewhat of a test for me when I first slapped them together and probably deserved to be explained more than they were. To that end, we'll look at one of the examples from yesterday and pick it apart, so that the pieces all make sense to, hopefully, any and every one. I aim to please :)

The example we'll work with is from part one of problem 2, where we looked to add the even columns and, separately, the odd columns and then print those totals at the end of each line. The original awk statement and resultant solution follow (check yesterday's awk post for the original dataset. It doesn't really make a difference insofar as this explanation will be concerned):

host # awk '{sum1=$1;sum2=$2;for (i=3;i<=NF;i++) {if ( i%2 ) {sum1 += $i; printf"%.2f ", $i}else {sum2 += $i; printf"%.2f ", $i}}printf"ODDS %.2f EVENS %.2f\n", sum1, sum2}' DATASET2

51.61 48.39 41.38 58.62 32.00 68.00 56.41 43.59 57.52 42.48 ODDS 284.75 EVENS 315.25
49.06 50.94 42.86 57.14 100.00 0.00 0.00 100.00 11.49 88.51 ODDS 259.96 EVENS 340.04
52.17 47.83 26.83 73.17 61.54 38.46 57.69 42.31 33.33 66.67 ODDS 273.23 EVENS 326.77
34.38 65.62 0.00 100.00 59.26 40.74 100.00 0.00 43.43 56.57 ODDS 257.07 EVENS 342.93
25.53 74.47 35.56 64.44 84.42 15.58 47.53 52.47 0.00 100.00 ODDS 243.04 EVENS 356.96


At first glance, I suppose that awk statement could look imposing. Fortunately, once you pull it apart, it's not all that bad. First, we'll write the awk in "plain English." Here's what the linear thought process would be if we just spelled it out:

To start out, we'll set the variable sum1 to the value of the first field. Then, we'll set the value of the variable sum2 to the value of the second field (This sets us up with sum1 holding the first "odd" field value and sum2 holding the first "even" field value). After this we'll iterate through a looping construct that begins by setting the value of the variable i to 3, continues until the value of the variable i is less than or equal to the number of fields on any given line (NF), and increments the value of i by 1 after every pass.

For each invocation of the loop (which goes until the value of i becomes less than or equal to the number of fields on the line, or record), we check the value of the modulo of i and 2. If you want to look up the definitions of modulo and modulus, I strongly encourage it, but only if you're really curious ;) For our purposes, it will serve to explain that i%2 (i modulo 2) acts as a check on the remainder of a division operation. So, if the value of i is 3, i%2 is equivalent to 3 divided by 2. Since 3 doesn't divide evenly by 2, it leaves a remainder of 1. That remainder is the value of the equation i%2. On the next pass (and every pass where an even number is concerned) the value of i%2 will be 0 since, for instance, 4 divides evenly by two, with a remainder of 0. Hopefully this isn't becoming more confusing than it started out being ;)

So, knowing what we now know, the "if statement" that gets run in every iteration of the outer "for loop" does a little bit of "backward figuring" (that is to say that the logic may not seem to be correct at first glance, although it is ;) The "if conditional" tests the value of i%2. For all even numbers this is equal to 0 and for all odd numbers it is equal to 1. So the statement "if ( i%2 )" is testing the value of that statement. In the case of awk, and most shell equations and their return codes, 1 equals true and 0 equals false. It's almost like saying: If "true" (the case for all odd numbers) do this and if "false" (the case for all even numbers), do the other thing... On to the next part... I never thought this would be so hard to explain ;)

This next part is pretty simple. For the odd numbers, the value of the variable sum1 is made equal to its old value plus the value of the field we're reading on this pass. If the value of i is 3, then we're checking field 3 (or $3, if you prefer). For the even numbers, the value of the variable sum2 is made equal to its old value plus the value of the field we're reading; same as with the odds. If i equals 4, we're adding the value of the i field (field 4, or $4) to the already existing value of sum2. For both instances, we're doing a simple printf to output that value to the terminal.

Now, to end it all, when the value of the variable i becomes less than or equal to the number of fields (NF) on the line (or record), we slip in a quick printf statement to print the values of the odd numbers (sum1) and even numbers (sum2) before moving on to the next line. This can be a confusing point because, as you may know, awk (like sed, etc) operates on every line of a file when you feed it one. It's for this reason that we're so careful with the bracketing. If we weren't able to control where the totals printed out, they'd print only after all the lines in the input file were processed, which isn't what we wanted.

Finally, here's the exact same equation, broken up across several lines (I "chose" to do everything on one line for yesterday's examples, because that makes it easy for me to re-run statements using my line editor in bash :) Hopefully, looking at it in this way (in a proper script-like format) will help shed some more light on the "structure" of the process, just like the previous paragraphs, hopefully, helped elucidate some of the finer points of the "execution" of the process:

awk '{sum1=$1;sum2=$2
for (i=3;i<=NF;i++) {
if ( i%2 ) {
sum1 += $i; printf"%.2f ", $i
}else {
sum2 += $i; printf"%.2f ", $i
}
}
printf"ODDS %.2f EVENS %.2f\n", sum1, sum2
}' DATASET2


if you slapped the above in a file, called it "awky.sh" and ran:

host # sh awky.awk

you'd get the exact same results as you got from the one-line version above.

Hopefully, this explanation has been helpful and, if not, please let me know what still remains a point of confusion for you. Unless there are a lot of requests for certain specific bits of info that would warrant another post, I'll be happy to help clear up little bits and pieces either via email or on the boards :)

Cheers,

, Mike




Please note that this blog accepts comments via email only. See our Mission And Policy Statement for further details.



, Mike




Please note that this blog accepts comments via email only. See our Mission And Policy Statement for further details.

Wednesday, November 19, 2008

Convoluted Column Arithmetic Examples Using Awk On Linux Or Unix

Hey There,

Today's going to be a "fun with awk" day. I figure we should have one now because we never had them in school when I was a kid... The topic, as the title suggests, has to do with columnar arithmetic or, less pompously put, performing arithmetic operations on columns or, even more accessibly, adding stuff up ;) It's somewhat like our older post on doing simple cumulative math with awk, but slightly more confusing.

The basic premise here is that you, I and the next guy have all seen the solution to many a question like: "Given a file filled with rows of space delimited numbers, how do I add up all the values for field 2 ($2) in awk so that I can get the total when awk is through processing my file?" ...or something to that effect. Knowing the fundamentals of performing arithmetic in awk can be a great asset to you at work (or, at play, if you like to add, subtract, multiply and divide for kicks ;), but, for the most part, only the most banal instances of its application are either used or queried for on the web (at least as far as my search engine testing has shown so far).

So, without further fanfare, we'll take a look at two sets of data (below) and some various (hopefully, not utterly pedestrian) ways to sort and manipulate the data. These are pulled from a series of posts I answered on the Daniweb.com Shell Scripting Forum regarding odd and even column operations (I try to only plagiarize myself ;). I found the questions interesting to answer and, hopefully, you'll find both the requests and their resolutions of some use, as well :) I've modified some of the solutions that I posted to the board for this blog post, as I found that, at some points, my quick (trying to be helpful) answers could be done a bit better with a little extra attention. Also, the entire thread isn't played out here and some additional problems haven't been included. There's only so much I can type ;)

The setup involves a file that contains these numbers in the columns and rows - or fields and records, as we'll refer to them from here on out - shown below. The initial problem uses this dataset. The result of the initial solution forms the dataset for all the problems to follow (shown below, in, hopefully, sensible order):

Data Set 1:

55 65 48 45 48 68 32 68 44 34 88 65
82 63 52 54 51 68 75 0 0 20 10 77
55 77 60 55 22 60 40 25 75 55 45 90
20 80 33 63 0 64 32 22 75 0 43 56
54 54 12 35 48 87 65 12 77 85 0 15


Problem 1: Given "Data Set 1" (conveniently placed in a file called "DATASET1"), for each pair of successive fields , using awk's built in arithmetic operators, convert each field by dividing it by the sum of the pair and multiplying each by 100 to produce recognizable relative-percentage output. So, for the first column, you would have the results of equations of the following order:

$1/$1+$2, $2/$1+$2, $3/$3+$4, $4/$3+$4, etc....

Solution 1: This can be worked out by the following awk command (technically not a "one-liner" since it exceeds the 65 character limit):

host # awk 'BEGIN{lasti=1}{for (i=1;i<=NF;i++) {if ( i%2==0 ) {y=$lasti+$i;printf("%.2f %.2f ", $lasti/y*100, $i/y*100)}lasti=i }printf"\n" }' DATASET1

This solution produces the following output, which will become "Data Set 2" (which will be put in a file called.... DATASET2. I couldn't come up with anything more clever under pressure ;)

45.83 54.17 51.61 48.39 41.38 58.62 32.00 68.00 56.41 43.59 57.52 42.48
56.55 43.45 49.06 50.94 42.86 57.14 100.00 0.00 0.00 100.00 11.49 88.51
41.67 58.33 52.17 47.83 26.83 73.17 61.54 38.46 57.69 42.31 33.33 66.67
20.00 80.00 34.38 65.62 0.00 100.00 59.26 40.74 100.00 0.00 43.43 56.57
50.00 50.00 25.53 74.47 35.56 64.44 84.42 15.58 47.53 52.47 0.00 100.00


Problem 2: From "Data Set 2," take each line and add up the all the odd fields and all the even fields per record. Then, as an added bonus, add up all the odd fields and all the even fields in all records. This was solved by the following awk statement (Note that, on the board, the sum for the first part of this problem was not printed as part of the solution, since it was being manipulated via an external array elsewhere within a script. For this example, I'm putting the totals for each line at the end of each line and anchoring them with text for easy distinction):

host # awk '{sum1=$1;sum2=$2;for (i=3;i<=NF;i++) {if ( i%2 ) {sum1 += $i; printf"%.2f ", $i}else {sum2 += $i; printf"%.2f ", $i}}printf"ODDS %.2f EVENS %.2f\n", sum1, sum2}' DATASET2

51.61 48.39 41.38 58.62 32.00 68.00 56.41 43.59 57.52 42.48 ODDS 284.75 EVENS 315.25
49.06 50.94 42.86 57.14 100.00 0.00 0.00 100.00 11.49 88.51 ODDS 259.96 EVENS 340.04
52.17 47.83 26.83 73.17 61.54 38.46 57.69 42.31 33.33 66.67 ODDS 273.23 EVENS 326.77
34.38 65.62 0.00 100.00 59.26 40.74 100.00 0.00 43.43 56.57 ODDS 257.07 EVENS 342.93
25.53 74.47 35.56 64.44 84.42 15.58 47.53 52.47 0.00 100.00 ODDS 243.04 EVENS 356.96


and for part 2 of problem 2 - to get the grand total of all even fields and grand total of all odd fields:

host # awk 'BEGIN{sum1=$1;sum2=$2}{for (i=1;i<=NF;i++) {if ( i%2 ) sum1 += $i;else sum2 += $i}}END{print "ODDS " sum1 " EVENS " sum2}' DATASET2

ODDS 1318.05 EVENS 1681.95


Problem 3: Given "Data Set 2," how could you divide every odd field by the grand total of all odd fields, and divide every even field by the grand total of all even fields (with minor modification to set the decimal precision from 2 to 4, since the resulting values will be well below 1% ;) - For example, you would want output that went through the data file and did "$1/1318.05 $2/1681.95, $3/1318.05..." etc. This can be accomplished by the following:

host # awk 'BEGIN{odds=1318.05;evens=1681.95}{for (i=1;i<=NF;i++) {if ( i%2 ) {odd=$i/odds; printf"%.4f ", odd}else {even=$i/evens; printf"%.4f ", even}}printf"\n";}' DATASET2

0.0348 0.0322 0.0392 0.0288 0.0314 0.0349 0.0243 0.0404 0.0428 0.0259 0.0436 0.0253
0.0429 0.0258 0.0372 0.0303 0.0325 0.0340 0.0759 0.0000 0.0000 0.0595 0.0087 0.0526
0.0316 0.0347 0.0396 0.0284 0.0204 0.0435 0.0467 0.0229 0.0438 0.0252 0.0253 0.0396
0.0152 0.0476 0.0261 0.0390 0.0000 0.0595 0.0450 0.0242 0.0759 0.0000 0.0330 0.0336
0.0379 0.0297 0.0194 0.0443 0.0270 0.0383 0.0640 0.0093 0.0361 0.0312 0.0000 0.0595


and here's an alternate way to get the same thing (combining problems 2 and 3 with the assumption that we don't know the exact values of the "odds" and "evens" variables I populated in the BEGIN section of problem 3):

host # echo `awk 'BEGIN{sum1=$1;sum2=$2}{for (i=1;i<=NF;i++) {if ( i%2 ) sum1 += $i;else sum2 += $i}}END{printf"%.4f %.4f", sum1,sum2}' DATASET2`|while read x y;do awk -v odds=$x -v evens=$y '{for (i=1;i<=NF;i++) {if ( i%2 ) {odd=$i/odds; printf"%.4f ", odd}else {even=$i/evens; printf"%.4f ", even}}printf"\n"}' DATASET2;done

0.0348 0.0322 0.0392 0.0288 0.0314 0.0349 0.0243 0.0404 0.0428 0.0259 0.0436 0.0253
0.0429 0.0258 0.0372 0.0303 0.0325 0.0340 0.0759 0.0000 0.0000 0.0595 0.0087 0.0526
0.0316 0.0347 0.0396 0.0284 0.0204 0.0435 0.0467 0.0229 0.0438 0.0252 0.0253 0.0396
0.0152 0.0476 0.0261 0.0390 0.0000 0.0595 0.0450 0.0242 0.0759 0.0000 0.0330 0.0336
0.0379 0.0297 0.0194 0.0443 0.0270 0.0383 0.0640 0.0093 0.0361 0.0312 0.0000 0.0595


And, hopefully, that's enough awk for now. Check out the Daniweb.com Shell Scripting Forum boards to see some of the great solutions other folks come up with (for some pretty bizarre problems) and, if it's just not your day, a few of my other monstrosity's ;)

Cheers,

, Mike




Please note that this blog accepts comments via email only. See our Mission And Policy Statement for further details.

Wednesday, May 28, 2008

Simple Arithmetic In Bash, Perl and Awk - More Porting

Greetings,

Today we're going to continue along on our series of posts dealing with porting code between the bash shell, Perl and awk. In previous posts, we've looked at the basics regarding simple string variables, simple one-dimensional arrays and associative arrays (sometimes referred to as hashes or "lookup tables.").

Before we move on to logical programming constructs (such as if-conditionals and while-loops), it's important to go over a few other basic concepts that require translation in order to work in the same manner in all three languages. Today we're going to demonstrate how each of bash, Perl and awk deal with simple arithmetic. Note that we won't be dealing specifically with floating point math (although it is possible to do) since that's slightly beyond the scope of this article (but it will be -- huge hint -- the subject of our next post in this series... variable scope, that is ;)

For our purposes today, we're going to assume that we need to solve five different arithmetic equations in each of our three languages. And, coincidentally enough, all five equations need to serve a distinctly different arithmetic purpose. We're going to have to take two integers and perform addition, subtraction, multiplication and division on them, and also extract the remainder of any imperfect divisions (defined herein as any division which doesn't have a remainder of 0). Note that, for all of our "bash" examples, the spaces (or lack thereof) in the equations are "required." Perl and awk will produce results with or without spaces between the operands.

1. Bash: In the bash shell, all of these actions are very simple to perform, and you have a more than a few options at your disposal depending on how you prefer to do them. The one way you can perform shell arithmetic that will work in older versions of the bash shell (or most any other shell) is to use the "expr" commmand. While this is, technically, an entirely separate program, it can come in handy if you get ahold of an older shell that can't perform arithmetic on its own. The syntax for our equations would be the following (We'll be assuming that the side explanations will be the same for Perl and awk to save on space):

host # expr 9 + 2
11
host # expr 9 - 2
7
host # expr 9 \* 2
18
host # expr 9 / 2
<--- Here you can see a limitation of simple integer math in the shell. 9 divided by 2 should be 4.5, but the shell doesn't understand the fraction.
4
host # expr 9 % 2
<--- And here's the reason we want to see the remainder of that division. This shows us that 1 integer was lost in the imperfect division.
1

The bash shell, however, will allow you to do simple arithmetic in a much more simplistic way. And this is it (we'll use the shell built-in "echo" to print the output to the screen):

host # echo $((9+2))
11
host # echo $((9-2))
7
host # echo $((9*2))
18
host # echo $((9/2))
4
host # echo $((9%2))
1


2. Perl: Perl, as we've mentioned in previous posts, provides easy access to the shell via the backtick operators and "system" function, but there's almost no need to ever use those, since Perl can do simple arithmetic on its own. In fact, depending upon how heavily you use a "system" resource from within a Perl program, the slower and more cumbersome that program will become. Using Perl's built-in functions and methods is almost always more efficient.

Here's an example of how we'd do the same arithmetic with Perl, using the command line execution statement (-e flag) method (again, we'll use a print function to spit the output to the terminal):

host # perl -e 'print 9 + 2 . "\n";'
11
host # perl -e 'print 9 - 2 . "\n";'
7
host # perl -e 'print 9 * 2 . "\n";'
18
host # perl -e 'print 9 / 2 . "\n";'
<--- Note, here, how Perl naturally deals with fractions!
4.5
host # perl -e 'print 9 % 2 . "\n";'
1


3. Awk: Awk makes performing arithmetic operations incredibly easy, as well. It, like Perl, also understands simple fractions and accounts for simple floating point arithmetic right out-of-the-box:

host # echo |awk '{print 9+2}'
11
host # echo |awk '{print 9-2}'
7
host # echo |awk '{print 9*2}'
18
host # echo |awk '{print 9/2}'
4.5
host # echo |awk '{print 9%2}'
1


And, that's all there is to it. As you can see, the difference between performing simple arithmetic in all three languages isn't that great. As we continue to examine porting code between these languages, you'll notice a lot of similarities (and a few minor differences ;) which will make the translation of one language to another very simple for you with a little practice and patience.

Our next porting post will deal with variable scope, which we'll both define and demonstrate .

Until then!

, Mike

Saturday, May 10, 2008

Finding the Number of Characters In A Variable Regardless Of Your Linux Or Unix Shell

Hey there,

Here's a simple enough task: Finding (or determining) the amount of characters in a string variable. In most Unix or Linux shells, this has become a trivial exercise. For instance, in bash or ksh, you can easily tell how many characters are in a particular string variable by either writing one line of code, or skipping right to the end and printing out the answer. By way of example:

host # x=thisIsMyVariable
host # echo ${#x}
16


And it's that simple. The variable x, which contains the string value "thisIsMyVariable", does, indeed, contain 16 elements (or characters). As you can see, in the more advanced shells, taking care of this is no problem.

However, in certain circumstances, you may be required to use a less-advanced, but more highly-portable, shell, like the original Bourne shell. In that case, this same sequence of commands would result in the following:

host # x=thisIsMyVariable
host # echo ${#x}
host #
<--- At best, you'll get zero here. Expect nothing. You might possibly get an error.

Our script attached today, uses the old-style expr (Well, it uses the new style expr with the old format and options, again, for maximum portability between systems and shells). It does the exact same thing that echo'ing ${#VARIABLE_NAME} does, but goes about it in a grueling and confusing manner. Remember back when you had to write scripts that took the shell's needs into consideration before your own? ;) Nowadays, things are much more intuitive.

Given a string, like "thisIsMyVariable," the following script will produce the exact same results. It will spit out how many characters are in that string, but take a longer, more confusing ,route to the answer. This is another good example of security through obfuscation as well. In general, having to use the expr command can be a hurdle for folks who've never used a shell that can't do arithmetic or string comparison on its own :)

Sample output (as boring as it is ;):

host # ./string.sh thisIsMyVariable
16


And now, you can get the string length no matter how limited your shell is!

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/sh

#
# string.sh - print out how many characters are in a string variable
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

if [ $# -ne 1 ]
then
echo "Usage: $0 string"
exit 1
fi

string=$1
echo $string|while read x
do
chars=`expr "$x" : '.*'`
echo $chars
done


, Mike

Friday, November 2, 2007

Simple Arithmetic in the Bourne Shell

Afternoon,

Most folks use shells like bash and ksh (myself included) because of the additional functionality they provide. Shells like sh, jsh, ash and the standard posix are more limited and don't come with a lot of bells and whistles.

Of course, working in a limited shell does have its advantages. For instance, if you write a script in sh, it'll probably work on most any system you port it to. Write in on Solaris and you can most likely run it on Solaris, HP-UX, SCO, Linux, etc.

One of the bonuses the more advanced shells come with is the ability to perform arithmetic simply. However, simply because the functionality exists overtly in the more advanced shells doesn't mean that, without a little practice, you can't perform arithmetic just as easily in "lesser" shells.

In sh (which we'll use as our example "simple" shell from this point forward) you can do arithmetic pretty easily if you know how to use the "expr" command.

Let's say you want to add 2 + 2 and assign that result to a variable. Simple enough, right? In ksh you could simply do:

a=2
let result=$a+$a
echo $result


And you're all set. Of course, it's not that much more difficult in sh. As shown below:

a=2
result=`expr $a + $a`
echo $result


Doesn't seem all that much more difficult, huh?

Basically, in sh you have to use expr. That's okay, because its on virtually every flavor of Unix available, as is sh. You get your result from expr (which simply evaluates expressions; arithmetic and otherwise) by calling it from between the backticks (``). Backticks in Unix are just a simple way of saying "replace what's within these backticks with the result of the expression, calculation, function or assignment executed within these backticks."

So, to break it down, sh simply does this:

a=2
result=`expr 2 + 2`
expr 2 + 2 returns 4
result=4


There are lots of things you can do like this in lesser shells. Ultimately, it's a user preference, but, if you're looking for maximum portability, taking advantage of the lesser shells is a great way to go. Virtually everything that can be done easily in more user-friendly shells can be done in lesser shells.

Sometimes it's simple, like this, and sometimes its beyond the point of confusing. For instance, faking arrays in sh isn't very complicated, but it can be very easy to lose track of. But that's for another day!

, Mike





Sunday, October 28, 2007

Floating Point Arithmetic and Percentage Comparison in Ksh!

Hello again,

Today, we've got a somewhat heavy script. If you're an administrator, or just a concerned user, you've probably run into a situation where you needed to be notified if a file got too large. This is a fairly common concern if you're going to have to do lots of extra work if you don't get some fair warning before the file fills up the partition it resides on!

Below is a little something I whipped up to keep tabs on pretty much any file. It involves several concepts, which we'll go over in the future. These include, mailing out to users from within the script, watching a file's size and comparing it with an "expected" size and using the shell's limited integer arithmetic to evaluate size and comparative percentage with simulated floating-point decimals.

Below: The script. Over the next few days or weeks, I'll revisit some of the finer points involved here, as they require way too much space when dealt with all at once!


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/ksh

#
# 2007 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

concerned_users="user1@xyz.com,user2@xyz.com"

if [ ! -f $db_file ]
then
(echo "Subject: Database File Missing!";echo;echo;echo "The file $db_file does not seem to exist!?";echo "From: root@xyz.com";for x in $concerned_users;do echo "To: $x";done;echo "Please check this out a.s.a.p. unless it is a known issue!")|/usr/lib/sendmail -t
exit 1
fi

db_file=/path/to/db.file
db_dusk=`/usr/bin/du -sk $db_file`
db_size=`echo $db_dusk|/usr/bin/awk '{print $1}'`
db_limit=2097152.20
let threshold=`echo 4 k ${db_size} $db_limit / p |/usr/bin/dc|/usr/bin/sed 's/\.//'`
threshold_pct=`echo $threshold|/usr/bin/sed 's/^\(.*\)\(..\)$/\1\.\2/'`

# Assuming 2Gb Crash Point - 2097152.2 Kb
# -- Start Warning At 85%

if [ $db_size -gt 1782579 ]
then
(echo "Subject: Database Approaching Maximum Capacity";echo "From: root@xyz.com";for x in $concerned_users;do echo "To: $x";done;echo "";echo "";echo "Database $db_file is currently at";echo "$db_size Kb";echo "This exceeds the 2Gb 85% threshold at ${threshold_pct}%.";echo "Please reduce the size immediately, if possible")|/usr/lib/sendmail -t
fi


Hopefully, this script will be helpful to you. I look forward to digging deeper into the specifics in future posts :)

, Mike





Wednesday, October 24, 2007

Simple But Useful: Finding the Highest Number

Hey There,

This is something you do every day, probably. Compare things. And then, based on whatever your objective is, you ferret out the one object that meets your requirements.

This is a really simple script, assuming input on the command line of any number of numbers, separated by spaces. When it's done, it will print out the largest number of the bunch.

Not super exciting, but fundamental and applicable to lots of things, depending on what you want to compare. Later on, I'll post the equivalent alpha version of this numeric scriptlet


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/ksh

#
# 2007 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

highest_number=0
for x in $@
do
if [ $x -gt $highest_number ]
then
highest_number=$x
fi
done
print "Highest Number is $highest_number"


Yes, today is my day of rest ;)

,Mike