Bash scripting 101: Chapter 4: IF he's jolly why is he loopy? (loopy loops)
we ended last chapter with a script to look if a hostname exists with different tld's
we'll start this one with one that can do international tld's as well
#!/bin/bash
test "${1}" = "" && echo 'script needs at least a domain name without tld to check' && exit 1
ORIGINAL_TLD="edu com gov net org"
INTERNATIONAL_TLD="se dk de uk us"
TOPLEVELDOMAINS="$ORIGINAL_TLD $INTERNATIONAL_TLD"
for TLD in $TOPLEVELDOMAINS
do
host $1.$TLD
done
nothing new there actually, we just combined something from scripts on the earlier page :-)
what if you want more international tld's?..just add them to INTERNATIONAL_TLD, what if you want one not in the list and don't want it NORMALLY in the variable/list(INTERNATIONAL_TLD) (that list is checked every time you run it, so it can get a bit much) ie..what if you just want to add "nu" tld for one time only?
well you can do that too
#!/bin/bash
test "${1}" = "" && echo 'script needs at least a domain name without tld to check' && exit 1
LOOKMEUP=$1
shift
ORIGINAL_TLD="edu com gov net org"
INTERNATIONAL_TLD="se dk de uk us"
for EXTRATLD in $@
do
MORETLD="$MORETLD $EXTRATLD"
shift
done
TOPLEVELDOMAINS="$ORIGINAL_TLD $INTERNATIONAL_TLD $MORETLD"
for TLD in $TOPLEVELDOMAINS
do
host $LOOKMEUP.$TLD
done
exit 1
SCREAM!!! you MAD person!!! you are trying to give me a headache..i KNEW it!
not at all, look how few "new" things are actually there? i'll just do explanations of the new and/or (in shellscripter parlance..(&&/||) )"complex stuff". ok..i'm sorry that shellscripter parlance was a bad joke
- #!/bin/bash
shebang line, (old news)
- test "${1}" = "" && echo 'script needs at least a domain name without tld to check' && exit 1
check for commandline arguments or exit with error message and code (old news)
- LOOKMEUP=$1
move first command line argument into LOOKMEUP variable (old news)
- shift
AHA! NEWS! shift moves the $1 one step, it repositions the contents of $@ by one (read the bash man file on shift)
in this case it moves host_2_lookup argument that we give the shellscript out of the way giving us access to the rest of the potential arguments
ie it makes/moves the content of $2 into $1, the content of $3 into $2 and so forth
- ORIGINAL_TLD="edu com gov net org"
set the original tld's into variagle ORIGINAL_TLD (old news)
- INTERNATIONAL_TLD="se dk de uk us"
put some international ones into INTERNATIONAL_TLD (old news)
- for EXTRATLD in $@
uh oh!...for every value in $@ (which contains a list of command line arguments) put the value into EXTRATLD...NOTE remember we 'shift'ed the $@ by one step above (point 4)
- do
ancient news, starts the do block
- MORETLD="$MORETLD $EXTRATLD"
MORETLD is the same as contents of MORETLD and the contents of EXTRATLD
so the first time it's empty and gets the first TLD you gave as second argument, then it's got the second argument and gets the third, and so forth
- shift
move the arguments in $@ one step so we keep grabbing a new one
- done
end the for/do/done block
- TOPLEVELDOMAINS="$ORIGINAL_TLD $INTERNATIONAL_TLD $MORETLD"
put into TOPLEVELDOMAINS the content of all our TLD's
- for TLD in $TOPLEVELDOMAINS
(old news)
- do
(old news)
- host $LOOKMEUP.$TLD
(old news)
- done
(old news)
- exit 0
exit this script with a 0 (completed successfully) in case we run this script from another script
now was that really so painful?
ok what about if you optionally want to pass an argument to the program "host"? say "-v" or "-t querytype"
it's doable too:
#!/bin/bash
test "${1}" = "" && echo -e "script needs at least a domain name without tld to check it also accepts -v and -t type switches equivalent to host commands -v -t type, ie\n $0 host2lookup -v -t type\n alt $0 host2lookup -t type -v\n any argument after the first (host2lookup) that is not -v or -t type\n is considered a tld\n ie nu es fi uk us\n" && exit 1
LOOKMEUP=$1
SHIFTCOUNT=0
if test "${2}" = "-v" && test "${3}" = "-t"
then
ARGUMENT="-v -t $4"
let SHIFTCOUNT=$SHIFTCOUNT+4
elif test "${2}" = "-v"
then
ARGUMENT="-v"
let SHIFTCOUNT=$SHIFTCOUNT+2
elif test "${2}" = "-t" && test "${4}" = "-v"
then
ARGUMENT="-v -t $3"
let SHIFTCOUNT=$SHIFTCOUNT+4
elif test "${2}" = "-t"
then
ARGUMENT="-t $3"
let SHIFTCOUNT=$SHIFTCOUNT+3
fi
if test $SHIFTCOUNT = 0
then
# you may have to replace "let SHIFTCOUNT++" below, with "let SHIFTCOUNT=$SHIFTCOUNT+1"
# depending on bash version 2.05 handles below, my 2.03 does NOT
let SHIFTCOUNT++
fi
shift $SHIFTCOUNT
ORIGINAL_TLD="edu com gov net org"
INTERNATIONAL_TLD="se dk de uk us"
for EXTRATLD in $@
do
MORETLD="$MORETLD $EXTRATLD"
shift
done
TOPLEVELDOMAINS="$ORIGINAL_TLD $INTERNATIONAL_TLD $MORETLD"
for TLD in $TOPLEVELDOMAINS
do
host $ARGUMENT $LOOKMEUP.$TLD
done
oookayyyyyy!!! you can stop screaming at me now! go out, have a coffee or a smoke or what ever, come back in 5 minutes with fresh bloodsugar and some fresh air :-)
ready? let's rock!
- #!/bin/bash
shebang line (old news)
- test "${1}" = "" && echo -e "script needs at least a domain name without tld to check it also accepts -v and -t type switches equivalent to host commands -v -t type, ie\n $0 host2lookup -v -t type\n alt $0 host2lookup -t type -v\n any argument after the first (host2lookup) that is not -v or -t type\n is considered a tld\n ie nu es fi uk us\n" && exit 1
if we don't get at least one argument, throwback help at the user then quit (exit) with an "error" (1), one thing worth noticing is the use of $0, the name the script got calledby is here, so if you call it "bla" it'll be bla, and if you call it "ifdomain" it'll be ifdomain
- LOOKMEUP=$1
grab the host2lookup from commandline argument 1($1) and put it into LOOKMEUP variable
- SHIFTCOUNT=0
set a counter for "shift", we want to shift the commandline arguments a bit if we have "-t type" or "-v" or even "-t type -v es" for instance. Set this counter to "0" to begin with
- if test "${2}" = "-v" && test "${3}" = "-t"
NEWS! "IF" or rather ..if command/then command/elif command/then command/else commands/fi
when you've stopped screaming at me you can go on reading :-)
it's quite simple if put in a logical way:
IF thisherecommand/expression is true(exit status 0)
THEN execute this command
ELIF (else if/if the previous didn't match) AND this_here_other_command/otherexpression is true
THEN execute this other command
ELSE (if none of the previous ones matched) do this command instead
FI end the "IF" block
the only thing that's important to remember is that it's the exit status of the program, ie not the number,
"test 0 = 0" will exit with (0)
"test 1 = 0" will exit with (1) because it's not so
but
"test 0 != 0" will exit with (1), because "!" before an expression means "NOT" so you are actually saying "test if 0 is NOT equal to zero, if it is equal, return FALSE (exit with error (1)) if it's NOT equal return true (exit with success (0))
this is boolean logic in a fashion but it depends on the exit status of the "program"/"command being run" and thus "help exit" and "help test" will be of great use to you
so basically what i am telling the script is...if second commandline argument "${2}" is "-v" AND (remember "&&" means "AND") third commandline argument "${3} is "-t" do the block after the next "then"
- then
start the block to do if the first "if" evaluated as true (exited with 0)
- ARGUMENT="-v -t $4"
put into the variable "ARGUMENT" the quoted string "-v -t $4" looking at the help message for this script and "man host" we see that "-t querytype" is the syntax thus -t should be followed by something like ANY or MX, and if:
$1 is taken by host2lookup
$2 is taken by -v (which we checked for)
$3 is taken by -t (which we also checked for
$4 should contain the type (if the user follows command syntax, if not, then ESBK (error sits behind keyboard)
- let SHIFTCOUNT=$SHIFTCOUNT+4
add "4" to the "0" of SHIFTCOUNT variable "host2lookup" "-v" "-t" "type" takes up 4 commandline arguments
- elif test "${2}" = "-v"
if the first one(point 5) wasn't true is this one? is the second commandline argument -v?
- then
this one is old news by now...start the second "conditional block" if the previous point was true
- ARGUMENT="-v"
set the variable ARGUMENT to "-v"
- let SHIFTCOUNT=$SHIFTCOUNT+2
add 2 to the 0 inside SHIFTCOUNT variable "host2lookup" and "-v" takes up 2 commandline arguments
- elif test "${2}" = "-t" && test "${4}" = "-v"
does $2 contain -t AND $4 contain -v? (WHOA..why did i jump $3? ..remember syntax? "-t type" that's why! if user follows syntax then $3 MUST contain type
- then
you know this one by now
- ARGUMENT="-v -t $3"
set variable ARGUMENT to contain "-v -t $3" i could have set it to contain "-t $3 -v" but i prefer to keep it in one order (no particular reason really), it's just like me using "ls -la" and some use "ls -al" same effect, different order of switches
- let SHIFTCOUNT=$SHIFTCOUNT+4
set SHIFTCOUNT to contain 4 (0+4=4) "host2lookup -t type -v" $1,$2,$3,$4 being used
- elif test "${2}" = "-t"
is commandline argument 2 "-t"?
- then
*tosses up hands* i'm not touching this one!
- ARGUMENT="-t $3"
set variable ARGUMENT to "-t $3" syntax is still -t type, "hostname2lookup -t type" puts type in $3
- let SHIFTCOUNT=$SHIFTCOUNT+3
make SHIFTCOUNT variable 3 (see previous point...3 arguments 3 shifts)
- fi
end the "if". fi ends if, it's just if spelled backwards (c'mon everyone saw that one coming right?)
- if test $SHIFTCOUNT = 0
if $SHIFTCOUNT didn't get anything above, that means we only have hostname2lookup as a commandline argument
- then
old news
- # ...
in "program" comments to help people using the program (soon i'll do all explaining there, except for the advanced stuff which i'll break down in lists like before)
- let SHIFTCOUNT++
aha ..."++" whadda ya mean "++"??? VARIABLE++ is a simple way if saying "add one to this one", there also exists ++VARIABLE, and --VAR and VAR--, if the ++ are before, then 1 is added to the variable BEFORE an eventual evaluation, if it's after then it's done AFTERthis one shouldn't be neccessary "shift" automatically assumes that it shifts from 1
but since i'm later using "shift $SHIFTCOUNT" and SHIFTCOUNT is set to 0, then i'd get a repeat of 1 if i didn't do this
this "if/fi" block could be replaced with (untested)
if test $SHIFTCOUNT < 1
then
shift 2
else
shift $SHIFTCOUNT
fi
i find my small if and then a standard way to handle it easier to debug
- fi
end the "if block"
- shift $SHIFTCOUNT
shift.. (see previous scripts) move the $1-"$what ever" that we've used for hostname2lookup eventual "-v" "-t" and "type" out of the way, giving us access to the rest of them easily
- ORIGINAL_TLD="edu com gov net org"
put the 5 of the original tld's into ORIGINAL_TLD variable
- INTERNATIONAL_TLD="se dk de uk us"
put "se dk de uk us" into the INTERNATIONAL_TLD variable
- for EXTRATLD in $@
for every commandline argument after what WAS prior to point 26 $1-$4 (which ever many we had) put this new one into EXTRATLD
- do
old news, starts the for "do" block
- MORETLD="$MORETLD $EXTRATLD"
MORETLD is equal to the contents of MORETLD variable and EXTRATLD, so if MORETLD is empty "" and EXTRA TLD this time around has "es", MORETLD becomes """es" which is in fact "es"
if the next value in $@ after the "es" is "uk" then it becomes MORETLD="es EXTRATLD" ie MORETLD="es uk" and so forth
- shift
each time the previous point runs, shift the commandline one step, (this one shouldn't really be needed), try commenting it out if you want
- done
heh really antique news
- TOPLEVELDOMAINS="$ORIGINAL_TLD $INTERNATIONAL_TLD $MORETLD"
put into TOPLEVELDOMAINS variable, the original TLD's, the INTERNATIONAL ones, and what ever extra ones user defined on the commandline
- for TLD in $TOPLEVELDOMAINS
for every value in TOPLEVELDOMAINS variable execute the below block of commands do-done
- do
old news
- host $ARGUMENT $LOOKMEUP.$TLD
host (the host command) $ARGUMENT put in eventual command line arguments (like -t type or -v or both). $LOOKMEUP which contains host2lookup and then .$TLD. a dot and the TLD variable that gets the value of the current "element" from TOPLEVELDOMAIN
- done
end for-do-done
- exit 0
exit with success (0)
ok that's schools out for today signal..scoot on home, take this with ya, and return later rested, refreshed and having experimented and i'll try to put up some more chapters