"comment out" code blocks | ||
---|---|---|
One line of shell code can be "commented out" using the "#" character. Sometimes however it would be nice to "comment out" more than one line of code, like the C "/* */" comments. One way to comment out multiple lines is this: : ' ,,,,,, ' After the ":" command (that returns "true") the rest of the code is a large string constant enclosed within 'single quotes'. Of course this works only if the code "commented-out" does not contain single quotes. |
"comment out" code blocks (2) | ||
---|---|---|
Another way to comment out multiple lines of code is the "here document" way: : << --END-COMMENT-- your comment here --END-COMMENT-- This way, there is no restriction with single quotes. Note that any delimiter can be used in place of "--END-COMMENT--". (tested with bash 2.05a) |
"comment out" code blocks (3) | ||
---|---|---|
(tested in bash 3 only) : << --END-COMMENT-- your comment here --END-COMMENT-- could cause problem if `somecommand` or $(somecommand) is used. : << --END-COMMENT-- `touch /tmp/foo` foo bar --END-COMMENT-- instead : << '--END-COMMENT--' `touch /tmp/foo` foo bar --END-COMMENT-- Additionally : can use also not-interpreted commands, e.g. : INGORED UP TO << '--END-COMMENT--' `touch /tmp/foo` foo bar --END-COMMENT-- |
cleaning up tmp files | ||
---|---|---|
I've seen too many scripts using massive number of tmp files, which is wrong in its self. But not only that, people tend to clean them up one at a time in a fashion such as if [ -a ${tmpFile} ]; then rm ${tmpFile}; fi This, when you use up to 10 or even 5 tmp files gets nasty. A quicker way of cleaning up such tmp files is to use a simple loop, I even perfer to use array's which are availible in Korn shell. Here is an example. clean() { tmpfiles[0]=${temp1} tmpfiles[1]=${temp2} for file in ${tmpfiles[*]} do if [ -a ${file} ]; then rm ${file} fi done This way, as you accumulate more and more tmp files, you need only to add one line to get it cleaned up. |
cleaning up tmp files (2) | ||
---|---|---|
Another way to clean up multiple temporary files is to create them within a subdirectory, i.e. TmpBase=${TMPDIR:=/tmp}/myscript.$$ mkdir "$TmpBase" || exit 1 # create directory chmod 700 "$TmpBase" || exit 1 # restrict access # Remove all temporary files after program termination # or at receiption of a signal: trap 'rm -rf "$TmpBase" >/dev/null 2>&1' 0 trap "exit 2" 1 2 3 15 # The following files will be remove automatically: input=$TmpBase/input output=$TmpBase/output #... |
Convert "relative" in "absolute" path name | ||
---|---|---|
In shell scripts it is often necessary to convert a relative path name, i.e. "../usr/../lib/somefile" to an absolute path name starting with a slash "/", i.e. "/lib/somefile". The following code fragment does exactly this: D=`dirname "$relpath"` B=`basename "$relpath"` abspath="`cd \"$D\" 2>/dev/null && pwd || echo \"$D\"`/$B" |
Positioning the cursor from within shell scripts | ||
---|---|---|
[This tip was first published within the SHELLdorado Newsletter 1/99] For some shell scripts it would be desirable, if the script could position the cursor to arbitrary (row, column) pairs (i.e. to display a status line, ...) The following shell function uses the "tput" command to move the cursor to the specified (row, column) position: # move cursor to row $1, col $2 (both starting with zero) # usage: writeyx message rowno colno writeyx () { tput cup $2 $3 echo "$1" } Example usage: clear # clear the screen writeyx "This is a centered message" 11 26 writeyx "press any key to continue..." 22 0 read dummy The "tput" comm! and looks up the escape command sequence for a feature needed for the current terminal. You can use it for other terminal related things, too: tput smso # "start mode shift out": usually # reverse echo "This is printed reverse" tput rmso # "reset mode shift out" All available capability names are listed on the terminfo(5) manual page. Portability: The "tput" command is available with the "terminfo" terminal information database |
Setting default values for variables | ||
---|---|---|
In shell scripts it's often useful to provide default values for script variables, i.e. if [ -z "$Host" ] then Host=`uname -n` fi For this kind of assignment the shell has a shorthand: : ${Host:=`uname -n`} This means: if the variable "Host" is not already set, execute the command "uname -n" and set the variable to the returned value. |
Getting a file into "memory" | ||
---|---|---|
Sometimes its convienient to have a file read into memory to work on it. The form that you take to accomplish this is an array data structure. In ksh88 the maximum is 1024 elements, however, on some of the more modern versions you can go much higher. To do this the following can be done: #/usr/bin/ksh typeset -i cnt=0 while read line do myarray[$cnt]=$line ((cnt = cnt + 1)) done < myfile # end of file--------- Now, if I want to access any line of that file, I simply use: ${ |
Find user's name | ||
---|---|---|
The full name of each user is available in the /etc/passwd file. If you would like to use the full name in your script instead of $LOGNAME, which simply returns the user's login name, you can declare the following variable in your script: fullname=`grep $LOGNAME /etc/passwd | cut -f 5 -d :` If you only want the first name, you would declare this variable: firstname=`grep $LOGNAME /etc/passwd | cut -f 5 -d : | cut -f 1 -d " "` |
Find user's name (2) | ||
---|---|---|
Since the full name is the 5th column of the file /etc/passwd, it's easy to look up the full name for a login name like "joe": awk -F: '$1 == name {print $5}' name=joe /etc/passwd The option "-F" tells awk to use ":" als field separator (instead of whitespace). |
Using "here-documents" instead of multiple "echo" | ||
---|---|---|
Multiple "echo" commands may be replaced by a "here-document". This makes the script faster and easier to read. Example: echo "Please enter your choice:" echo "1 - list current directory" echo "2 - list current users" echo "3 - log off" may be replaced with cat < |
Using "here-documents" instead of multiple "echo" (2) | ||
---|---|---|
# you can also turn multi-echos into a single echo echo " Welcome to Foo.Bar v0.8 ======================= Press enter to continue... "; |
To find idle users | ||
---|---|---|
w | gawk ' BEGIN { FIELDWIDTHS = "9 11 13 10 8 7 7 14" } NR > 2 { idle = $5 sub(/^ */, "", idle) if ( idle == "" ) idle = 0 if (idle ~ /:/) { split(idle, t, ":") idle = t[1] * 60 + t[2] #Converts idle time into seconds } if (idle ~ /days/) idle *= 24*60*60 print $1, $2, idle }' |
Using ksh builtins instead of external commands | ||
---|---|---|
Many times, scripters will use external commands like basename, dirname and tr because they don't realize they can instead use ksh builtins. An added bonus is the builtins are faster and require less system resources because no sub-process is spawned. basename replacement: --------------------- $ fullfile="/some/dir/file.txt" # replaced: file=$(basename $fullfile) $ file=${fullfile##*/} $ echo $file file.txt dirname replacement: -------------------- $ fullfile="/some/dir/file.txt" # replaced: dir=$(dirname $fullfile) $ dir=${fullfile%/*} $ echo $dir /some/dir tr replacements: ---------------- $ word="MiXeD" # replaced: word=$(echo $word | tr [A-Z] [a-z]) $ typeset -l word $ echo $word mixed # replaced: word=$(echo $word | tr [a-z] [A-Z]) $ typeset -u word $ echo $word MIXED |
KSH build-in networking functions | ||
---|---|---|
[Note: the following examples will work only with standard ksh implementations. They will not work with the Linux Korn Shell pdksh.] Most Korn Shells (/bin/ksh) have sparsely documented, build-in networking functions. Example: $ date= $ read date < /dev/tcp/127.0.0.1/13 $ echo $date Wed Feb 10 00:45:39 MET 1999 This command opens a TCP connection to the IP address 127.0.0.1 (the local loopback IP address), and connects to the port "13" (daytime, see /etc/services). The current date and time is returned, and assigned to the variable "date". Note that the "/dev/tcp/*" directories do not have to exist; the file names are special to the Korn Shell and are interpre! ted by the shell internally. Only numerical ip addresses and port numbers are supported; "read date < /dev/tcp/localhost/daytime" does not work. |
"Normalize" input field separators | ||
---|---|---|
Script programmers sometimes have to process input that consists of fields separated by whitespace, i.e. field1 field 2 |
To Reverse a File | ||
---|---|---|
######## TO PRINT FILE IN REVERSE ORDER BY LINE #############3 if [ $# -ne 1 ] then echo "Usage reverse_file |
Script debugging settings | ||
---|---|---|
Most shell script programmers know the command set -vx to print each script command before execution. Sometimes the following flags are useful, too: set -e # terminate the script at first error set -u # unset variables are fatal errors |
Enable "set -x" for all functions | ||
---|---|---|
Tracing can be enabled for a KornShell script by using "set -x", but this will have no effect on functions within the script. The following line will enable tracing for all functions in a script: typeset -ft $(typeset +f) Note that this will not work for BASH. [Idea is from Dan Mercer |
Swapping stdout and stderr | ||
---|---|---|
In scripts it's often useful not to filter standard output (i.e. cmd | filter), but stderr. This may be done using the following command: cmd 3>&1 1>&2 2>&3 It's even possible to filter both standard output and standard error: ( ( cmd | ... process stdout ) 3>&1 1>&2 2>&3 ) | \ ... process stderr 3>&1 1>&2 2>&3 The last file descriptor operations restore the normal meaning of stdin and stdout. |
Quickly comment/uncomment whole scripts | ||
---|---|---|
#!/usr/bin/ksh #set -x #-----VARIABLES # You must comment out one of the two VAR lines below depending on whether you want comments turned on or off in front of all your executable commands. # The VAR line below, when uncommented, will comment out all commands with $VAR in front of them #VAR=": #"; export VAR # The VAR line below, when uncommented, will allow execution of all commands with $VAR in fron of them. VAR=""; export VAR #-----MAIN $VAR date |
Find yesterday's date | ||
---|---|---|
A simple way, to find out yesterdays date: #!/usr/bin/ksh ############################ ### set the TZ env variable ############################ TZ=GMT+24 /usr/bin/date +%m%d%Y TZ specifies the time zone in which the time and date are written. If you set the time zone 24 hours forward, date will give yesterdays date back |
Print this post
No comments:
Post a Comment