KSHtips

Nice set of scripting tips for KSH (unknow source, probably somewhere on the internet)

Special shell variables
There are some variables which are set internally by the shell and which are
available to the user:

    $1 - $9       these variables are the positional parameters.
    $0            the name of the command currently being executed.
    $argv[20]     refers to the 20th command line argument
    $#            the number of positional arguments given to this
                  invocation of the shell.
    $?            the exit status of the last command executed is
                  given as a decimal string.  When a command
                  completes successfully, it returns the exit status
                  of 0 (zero), otherwise it returns a non-zero exit
                  status.
    $$            the process number of this shell - useful for
                  including in filenames, to make them unique.
    $!            the process id of the last command run in
                  the background.
    $-            the current options supplied to this invocation
                  of the shell.
    $*            a string containing all the arguments to the
                  shell, starting at $1.
    $@            same as above, except when quoted :
                  "$*" expanded into ONE long element : "$1 $2 $3"
                  "$@" expanded into THREE elements : "$1" "$2" "$3"
    shift   : $2 -> $1 ...)

special characters

The special chars of the Korn shell are :
    $    #  ?  [  ]  *  +  &  |  (  )  ;  `  "  '
- A pair of simple quotes '...' turns off the significance of ALL enclosed
  chars
- A pair of double quotes "..." : idem except for $ ` " 
- A '' shuts off the special meaning of the char immediately to its right.
  Thus, $ is equivalent to '$'.
- In a script shell :
    #       : all text that follow it up the newline is a comment
           : if it is the last char on a line, signals a continuation line
              qui suit est la continuation de celle-ci

Evaluating shell variables
The following set of rules govern the evaluation of all shell variables.

    $var                  signifies the value of var or nothing,
                          if var is undefined.
    ${var}                same as above except the braces enclose
                          the name of the variable to be substituted.
    +-------------------+---------------------------+-------------------+
    | Operation         | if str is unset or null   | else              |
    +-------------------+---------------------------+-------------------+
    | var=${str:-expr}  | var= expr                 | var= ${string}    |
    | var=${str:=expr}  | str= expr ; var= expr     | var= ${string}    |
    | var=${str:+expr}  | var becomes null          | var= expr         |
    | var=${str:?expr}  | expr is printed on stderr | var= ${string}    |
    +-------------------+---------------------------+-------------------+

The if statement
The if statement uses the exit status of the given command

        if test
        then
            commands     (if condition is true)
        else
            commands     (if condition is false)
        fi

if statements may be nested:

        if ...
        then ...
        else if ...
        ...
        fi
        fi

Test on numbers :

    ((number1 == number2))
    ((number1 != number2))
    ((number1   number2))
    ((number1 >  number2))
    ((number1 = number2))
    ((number1 >= number2))
        Warning : 5 different possible syntaxes (not absolutely identical) :
            if ((x == y))
            if test $x -eq $y
            if let "$x == $y"
            if [ $x -eq $y ]
            if [[ $x -eq $y ]]

Test on strings: (pattern may contain special chars)

    [[string  =  pattern]]
    [[string  != pattern]]
    [[string1   string2]]
    [[string1 >  string2]]
    [[ -z string]]                  true if length is zero
    [[ -n string]]                  true if length is not zero
        Warning : 3 different possible syntaxes :
            if [[ $str1 = $str2 ]]
            if [ "$str1" = "$str2" ]
            if test "$str1" = "$str2"

Test on objects : files, directories, links ...

    examples :
            [[ -f $myfile ]]            # is $myfile a regular file?
            [[ -x /usr/users/judyt ]]   # is this file executable?
    +---------------+---------------------------------------------------+
    | Test          | Returns true if object...                         |
    +---------------+---------------------------------------------------+
    | -a object     | exist; any type of object                         |
    | -f object     | is a regular file or a symbolic link              |
    | -d object     | is a directory                                    |
    | -c object     | is a character special file                       |
    | -b object     | is a block special file                           |
    | -p object     | is a named pipe                                   |
    | -S object     | is a socket                                       |
    | -L object     | is a symbolic (soft) link with another object     |
    | -k object     | object's "sticky bit" is set                      |
    | -s object     | object isn't empty                                |
    | -r object     | I may read this object                            |
    | -w object     | I may write to (modify) this object               |
    | -x object     | object is an executable file                      |
    |               |        or a directory I can search                |
    | -O object     | I ownn this object                                |
    | -G object     | the group to which I belong owns object           |
    | -u object     | object's set-user-id bit is set                   |
    | -g object     | object's set-group-id bit is set                  |
    | obj1 -nt obj2 | obj1 is newer than obj2                           |
    | obj1 -ot obj2 | obj1 is older than obj2                           |
    | obj1 -ef obj2 | obj1 is another name for obj2 (equivalent)        |
    +---------------+---------------------------------------------------+

The logical operators
You can use the && operator to execute a command and, if it is successful,
execute the next command in the list. For example:

        cmd1 && cmd2

cmd1 is executed and its exit status examined. Only if cmd1 succeeds is
cmd2 executed. You can use the || operator to execute a command and, if it
fails, execute the next command in the command list.

        cmd1 || cmd2

Of course, ll combinaisons of these 2 operators are possible. Example :

        cmd1 || cmd2 && cmd3

Math operators
First, don't forget that you have to enclose the entire mathematical
operation within a DOUBLE pair of parentheses. A single pair has a
completely different meaning to the Korn-Shell.

        +-----------+-----------+-------------------------+
        | operator  | operation | example                 |
        +-----------+-----------+-------------------------+
        | +         | add.      | ((y = 7 + 10))          |
        | -         | sub.      | ((y = 7 - 10))          |
        | *         | mult.     | ((y = 7 * 4))           |
        | /         | div.      | ((y = 37 / 5))          |
        | %         | modulo    | ((y = 37 + 5))          |
        |           | shift     | ((y = 2#1011  2))       |
        | >>        | shift     | ((y = 2#1011 >> 2))     |
        | &         | AND       | ((y = 2#1011 & 2#1100)) |
        | ^         | excl OR   | ((y = 2#1011 ^ 2#1100)) |
        | |         | OR        | ((y = 2#1011 | 2#1100)) |
        +-----------+-----------+-------------------------+

Controlling execution

    goto my_label
    ......
    my_label:
  -----
    case value in
        pattern1) command1 ; ... ; commandN;;
        pattern2) command1 ; ... ; commandN;;
            ........
        patternN) command1 ; ... ; commandN;;
    esac
        where : value    value of a variable
                pattern  any constant, pattern or group of pattern
                command  name of any program, shell script or ksh statement
        example 1 :
            case $advice in
                [Yy][Ee][Ss])   print "A yes answer";;
                [Mm]*)          print "M followed by anything";;
                +([0-9))        print "Any integer...";;
                "oui" | "bof")  print "one or the other";;
                *)              print "Default";;
        example 2 :     Creating nice menus
            PS3="Enter your choice :"
            select menu_list in English francais
            do
                case $menu_list in
                    English)  print "Thank you";;
                    francais) print "Merci";;
                    *)        print "???"; break;;
                esac
            done
  -----
    while( logical expression)
    do
        ....
    done
    while :                 # infinite loop
        ....
    done
    while read line         # read until an EOF (or <crtl_d> )
    do
        ....
    done  fname             # redirect input within this while loop
    until( logical expression)
    do
        ....
    done <fin >fout         # redirect both input and output
  -----
    for name in 1 2 3 4     # a list of elements
    do
        ....
    done
    for obj in *            # list of every object in the current directory
    do
        ....
    done
    for obj in * */*        # $PWD and the next level below it contain
    do
        ....
    done
  -----
    break;                  # to leave a loop (while, until, for)
    continue;               # to skip part of one loop iteration
                            # nested loops are allowed in ksh
  ----
    select ident in two # a list of identifiers
    do
        case $ident in
            one) ....... ;;
            two) ..... ;;
            *) print "none" ;;
        esac
    done

Debug mode

    > ksh -x script_name
  or, in a 'shell script' :
    set -x          # start debug mode
    set +x          # stop  debug mode

Examples
Example 1 : loops, cases ...

    #!/bin/ksh
    USAGE="usage :  fmr [dir_name]"	# how to invoke this script
    print "
        +------------------------+
        | Start fmr shell script |
        +------------------------+
    "
    function fonc
    {
    echo "Loop over params, with shift function"
    for i do
        print "parameter $1"    # print is equivalent to echo
        shift
    done                        # Beware that $# in now = 0 !!!
    }
    echo "Loop over all ($#) parameters : $*"
    for i do
        echo "parameter $i"
    done
                                #----------------------
    if (( $# > 0 ))             # Is the first arg. a directory name ?
    then
        dir_name=$1
    else
        print -n "Directory name:"
        read dir_name
    fi
    print "You specified the following directory; $dir_name"
    if [[ ! -d $dir_name ]]
    then
        print "Sorry, but $dir_name isn't the name of a directory"
    else
        echo "-------- List of directory $dir_name -----------------"
        ls -l $dir_name
        echo "------------------------------------------------------"
    fi
                                  #----------------------
    echo "switch on #params"
    case $# in
        0) echo "command with no parameter";;
        1) echo "there is only one parameter : $1";;
        2) echo "there are two parameters";;
        [3,4]) echo "3 or 4 params";;
        *) echo "more than 4 params";;
    esac
                                  #----------------------
    fonc
    echo "Parameters number (after function fonc) : $#"
                                  #------- To read and execute a command
    echo "==> Enter a name"
    while read com
    do
        case $com in
            tristram) echo "gerard";;
            guglielmi) echo "laurent";;
            dolbeau) echo "Jean";;
            poutot) echo "Daniel ou Claude ?";;
            lutz | frenkiel) echo "Pierre";;
            brunet) echo "You lost !!!"; exit ;;
            *) echo "Unknown guy !!! ( $com )"; break ;;
        esac
        echo "==> another name, please"
    done
                                  #------ The test function :
    echo "Enter a file name"
    read name
    if [ -r $name ]
    then echo "This file is readable"
    fi
    if [ -w $name ]
        then echo "This file is writable"
    fi
    if [ -x $name ]
        then echo "This file is executable"
    fi
                                  #------
    echo "--------------- Menu select ----------"
    PS3="Enter your choice: "
    select menu_list in English francais quit
    do
        case $menu_list in
            English)   print "Thank you";;
            francais)  print "Merci.";;
            quit)       break;;
            *)       print " ????";;
        esac
    done
    print "So long!"

Example 2 : switches

    #!/bin/ksh
    USAGE="usage: gopt.ksh [+-d] [ +-q]"    # + and - switches
    while getopts :dq arguments             # note the leading colon
    do
      case $arguments in
        d) compile=on;;                     # don't precede d with a minus sign
       +d) compile=off;;
        q) verbose=on;;
       +q) verbose=off;;
       ?) print "$OPTARG is not a valid option"
           print "$USAGE";;
      esac
    done
    print "compile=$compile - verbose= $verbose"

Example 3

    ###############################################################
    # This is a function named 'sqrt'
    function sqrt            # square the input argument
    {
        ((s = $1 * $1 ))
    }
    # In fact, all KornShell variables are, by default, global
    # (execpt when defined with typeset, integer or readonly)
    # So, you don't have to use 'return $s'
    ###############################################################
    # The shell script begins execution at the next line
    print -n "Enter an integer : "
    read an_integer
    sqrt $an_integer
    print "The square of $an_integer is $s"

Example 4

    #!/bin/ksh
    ############ Using exec to do I/O on multiple files ############
    USAGE="usage : ex4.ksh file1 file2"
    if (($# != 2))                    # this script needs 2 arguments
    then
        print "$USAGE"
        exit 1
    fi

    ############ Both arguments must be readable regular files
    if [[ (-f $1) && (-f $2) && (-r $1) && (-r $2) ]]
    then                              # use exec to open 4 files
        exec 3 <$1                    # open $1 for input
        exec 4 <$2                    # open $2 for input
        exec 5> match                 # open file "match" for output
        exec 6> nomatch               # open file "nomatch" for output
    else                              # if user enters bad arguments
        print "$        USAGE"
        exit 2
    fi
    while read -u3 lineA              # read a line on descriptor 3
    do
        read -u4 lineB                # read a line on descriptor 4
        if [ "$lineA" = "$lineB" ]
        then                          # send matching line to one file
            print -u5 "$lineA"
        else                          # send nonmatching lines to another
            print -u6 "$lineA; $lineB"
        fi
    done

    print "Done, today : $(date)"     # $(date) : output of 'date' command
    date_var=$(date)                  # or put it in a variable
    print " I said $date_var"         # and print it...

Example 5

    ############ String manipulation examples ##################
    read str1?"Enter a string: "
    print "nYou said : $str1"
    typeset -u  str1                  # Convert to uppercase
    print "UPPERCASE: $str1"
    typeset -l str1                   # Convert to lowercase
    print "lowercase: $str1"
    typeset +l str1                   # turn off lowercase attribute
    read str2?"Enter another one: "
    str="$str1 and $str2"             #concatenate 2 strings
    print "String concatenation : $str"
        # use '#'  to delete from left
        #     '##' to delete all
        #     '%'  to delete all
        #     '%%' to delete from right
    print "nRemove the first 2 chars -- ${str#??}"
    print "Remove up to (including) the first 'e' -- ${str#*e}"
    print "Remove the first 2 words -- ${str#* * }"
    print "nRemove the last 2 chars -- ${str%??}"
    print "Remove from last 'e' -- ${str%e*}"
    print "Remove the last 2 tokens -- ${str% * *}"
    print "length of the  string= ${#str}"
    ########################
    # Parsing strings into words :
    typeset -l line                     # line will be stored in lowercase
    read finp?"Pathname of the file to analyze: "
    read fout?"Pathname of the file to store words: "
    # Set IFS equal to newline, space, tab and common punctuation marks
    IFS="
        ,. ;!?"
    while read line                     # read one line of text
    do                                  # then Parse it :
        if [[ "$line" != "" ]]          # ignore blank lines
        then
            set $line                   # parse the line into words
            print "$*"                  # print each word on a separate line
        fi
    done < $finp > $fout                # define the input & output paths
    sort $fout | uniq | wc -l           # UNIX utilities

rrd_add_item .pl

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.