Ksh Scripting
Contents Principle
of Script
|
arrname[1]=4 | To fill in |
print ${arraname[1]} | To print out |
${arrname[*]} | Get all elements |
${#arrname[*]} | Get the number of elements |
There are happily no declarations of variables needed in ksh. One cannot have decimals only integers.
Branching
if [[ $value -eq 7 ]];then
print "$value is 7"
fi
or:
if [[ $value -eq 7 ]]
then
print "$value is 7"
fi
or:
if [[ $value -eq 7 ]];then print "$value is 7";fi
if [[ $name = "John" ]];then
print "Your welcome, ${name}."
else
print "Good bye, ${name}!"
fi
if [[ $name = "John" ]];then
print "Your welcome, ${name}."
elif [[ $name = "Hanna" ]];then
print "Hello, ${name}, who are you?"
else
print "Good bye, ${name}!"
fi
case $var in
john|fred) print $invitation;;
martin) print $declination;;
*) print "Wrong name...";;
esac
Looping
while [[ $count -gt 0 ]];do
print "\$count is $count"
(( count -= 1 ))
done
until [[ $answer = "yes" ]];do
print -n "Please enter \"yes\": "
read answer
print ""
done
for foo in $(ls);do
if [[ -d $foo ]];then
print "$foo is a directory"
else
print "$foo is not a directory"
fi
done
One can skip the rest of a loop and directly go to the next iteration with: "continue".
while read line
do
if [[ $line = *.gz ]];then
continue
else
print $line
fi
done
One can also prematurely leave a loop with: "break".
while read line;do
if [[ $line = *!(.c) ]];then
break
else
print $line
fi
done
Command Line Arguments
(Officially they are called "positional parameters")
The number of command line arguments is stored in $#
so one can check
for arguments with:
if [[ $# -eq 0 ]];then
print "No Arguments"
exit
fi
The single Arguments are stored in $1, ....$n
and all are in $* as one string. The
arguments
cannot
directly be modified but one can reset the hole commandline for another
part of the program.
If we need a first argument $first for the rest of the program we do:
if [[ $1 != $first ]];then
set $first $*
fi
One can iterate over the command line arguments with the help of the
shift command. Shift indirectly removes the first
argument.
until [[ $# -qe 0 ]];do
# commands ....
shift
done
One can also iterate with the for loop, the default with for is $*:
for arg;do
print $arg
done
The program name is stored in $0 but it contains the path also!
Comparisons
To compare strings one uses "="
for equal and "!=" for not equal.
To compare numbers one uses "-eq"
for equal "-ne" for not equal as
well as "-gt" for greater than
and "-lt" for less than.
if [[ $name = "John" ]];then
# commands....
fi
if [[ $size -eq 1000 ]];then
# commands....
fi
With "&&" for "AND" and "||" for "OR" one can combine statements:
if [[ $price -lt 1000 || $name = "Hanna" ]];then
# commands....
fi
if [[ $name = "Fred" && $city = "Denver" ]];then
# commands....
fi
Variable Manipulations
Variables that contain a path can very easily be stripped of it: ${name##*/}
gives you just the filename.
Or if one wants the path: ${name%/*}. %
takes
it away from the left and # from the right.
%% and ## take the longest possibility while % and # just take the
shortest one.
例如:
#!/usr/bin/ksh
print
'${0#*/}='${0#*/}
print '${0##*/}='${0##*/}
print
'${0%/*}='${0%/*}
print '${0%%/*}='${0%%/*}
#
lxs/shellscript/strip.sh
${0#*/}=shellscript/strip.sh
${0##*/}=strip.sh
${0%/*}=lxs/shellscript
${0%%/*}=lxs
If we wanted $foo or if not set 4 then: ${foo:-4}
but it still remains unset. To change that we use:
${foo:=4}
This is very important if our program relays on a certain vaiable: ${foo:?"foo not set!"}
例如:此時(shí)foo沒(méi)有賦值;
#!/usr/bin/ksh
#foo="camel"
print
${foo:?"foo not set"}
print "hello world"
# ./tt.sh
./tt.sh[4]:
foo: foo not set
下面的例子將foo賦值,,則hello world被輸出,;
#!/usr/bin/ksh
foo="camel"
print
${foo:?"foo not set"}
print "hello world"
# ./tt.sh
camel
hello
world
${foo:+1} gives one if $foo is set, otherwise nothing.
Ksh Regular Expressions
Ksh has it's own regular expressions.
Use an * for any string. So to get all the
files ending it .c use *.c.
A single character is represented with a .
So all the files starting with any sign followed bye 44.f can be fetched
by: 44.f.
Especially in ksh there are quantifiers for whole patterns:
(pattern) matches zero or one times the
pattern.
*(pattern) matches any time the pattern.
+(pattern) matches one or more time the
pattern.
@(pattern) matches one time the pattern.
!(pattern) matches string without the
pattern.
So one can question a string in a variable like: if [[ $var = fo@(?4*67).c ]];then ...
Functions
A function (= procedure) must be defined before it is called, because
ksh is interpreted at run time.
It knows all the variables from the calling shell except the commandline
arguments. But has it's
own command line arguments so that one can call it with different values
from different places in
the script. It has an exit status but cannot return a value like a c
funcition
can.
One can make one in either of the following two ways:
function foo {
# commands...
}
foo(){
# commands...
}
To call it just put it's name in the script: foo. To give it
arguments
do: foo arg1 arg2 ...
The arguments are there in the form of $1...$n
and $* for all at once like in the main
code.
And the main $1 is not influenced bye the
$1 of a particular function.
The return statement exits the function imediately with the specified return value as an exit status.
例如:
#!/usr/bin/ksh
print
$1
function foo {
print $1
return 100
}
foo "hello
world"
if [[ $? -eq 100 ]]; then
print "foo is successful"
fi
#
./fnc.sh camel
camel
hello world
foo is successful
Data Redirection
Data redirection is done with the follwoing signs: "> >> < <<". Every program has at least a
standardinput, standardoutput and standarderroroutput. All of these can be redirected.
For writing into a new file or for overwriting a file do: command > file
For appending to a file do: command >> file
To redirect the error output of a command do: command 2> file
To discard the error alltogether do: command 2>/dev/null
To put the error to the same location as the normal output do: command 2>&1
If a program needs a file for input over standard input do: command < file
command < infile > outfile
command < infile > outfile 2>/dev/null
Every unix command can take it's commands from a text like listing with:
command <<EOF
input1
input2
input3
EOF
From eof to eof all is feeded into the above mentioned command.
Pipes
For
a serial processing of data from one command to the next do:
command1 | command2 | command3 ...
e.g. last | awk '{print $1}' | sort -u.
Coprocesses
One can have one background process with which one can comunicate with read -p and print -p. It is started with command |&. If one uses: ksh |& then this shell in the background will do everything for us even telnet and so on: print -p "telnet hostname".
Read Input from User and from Files
From a user we read with: read var. Then the users can type something in. One should first print something like: print -n "Enter your favorite haircolor: ";read var; print "". The -n suppresses the newline sign.
To get each line of a file into a variable iteratively do:
{ while read myline;do
# process $myline
done } < filename
To catch the output of a pipeline each line at a time in a variable use:
last | sort | {
while read myline;do
# commands
done }
Special Variables
$# Number
of arguments
on commandline.
$? Exit status of
last
command.
$$ Process id of
current
program.
$! Process id of
last
backgroundjob or background function.
$0 Program name
including
the path if started from another directory.
$1..n Commandline
arguments,
each at a time.
$* All commandline
arguments
in one string.
Action on Success or on Failure of a Command
If one wants to do a thing only if a command succeded then: command1 && command2. If the second command has to be performed only if the first one failed, then: command1 || command2.
Trivial Calculations
Simpe calculations are done with either a "let" in front of it or within (( ... )). One can increment a variable within the (( )) without a "$": (( a+=1 )) or let a+=1.
Numerical Calculations using "bc"
For bigger caluculations one uses "bc" like: $result=$(print "n=1;for(i=1;i<8;i++)n=i*n;n"|bc)
"grep"
Search for the occurence of a pattern in a file: grep
'pattern' file. If one just wants to know how often soemthing
occurs
in a file, then: grep -c 'pattern file.
This
can be used in a script like:
if [[ $(grep -c 'pattern' file) != 0 ]];then
......;fi.
The condition is fullfilled if the pattern was found.
"sed"
Sed means stream line editor. It searches like grep, but is then able to replace the found pattern. If you want to change all occurences of "poor" with "rich", do: sed -e 's/poor/rich/g' filename. Or what is often seen in software packages, that have to be compiled after getting a propper configuration, is a whole file stuffed with replacements patterns like: /@foo@/s;;king;g. This file with inumerable lines like that has to be given to sed with: sed -f sedscript filename. It then precesses each line from file with all the sed commands in the sedscript. (Of course sed can do much more:-))
"awk"
Awk can find and process a found line with several tools: It can
branch,
loop, read from files and also print out to files or to the screen, and
it can do arithmetics.
For example: We have a file with lines like: Fred 300 45 70 but
hundreds of them. But some lines have a "#" as the first sign
of them and we have to omit these ones for both, processing and output.
And we want to have lines as output like: 415 Fred where 415 is
the sum of 300, 45 and 70. Then we call on awk:
awk '$1 !~ /^#/ && $0 ~ /[^ ]/ {print $2+$3+$4,"\t",$1}' filename.
This ignores lines with a "#" at the beginning of the first field and also blank lines. It then prints the desired sum and the $1 ist only printed after a tab. This is the most trivial use of awk only.
Check my AWK programming introduction bye clicking on this sentence!
"perl"
Perl is a much richer programming language then ksh, but still one can do perl commands from within a ksh script. This might touch Randal, but it's true. Let's say you want to remove all ^M from a file, then take perl for one line in your ksh script:
perl -i -ep 's/\015//g' filename.
Perl can do an infinite amount of things in many different ways. For anything bigger use perl instead of a shell script.
|
來(lái)自: neumann > 《我的圖書(shū)館》