Subject: Bash Lecture Summary (Rev 3)

From: Shlomi Fish <[email-masked]>
Date: Sun, 5 Nov 2000 21:56:45 +0200 (IST)

Voila. Added section about programming constructs. You can find it on its
webpage:

http://vipe.technion.ac.il/~shlomif/lecture/Bash/

and naturally the text is included below.

Enjoy and comment,

	Shlomi Fish

BTW, assuming me writing the summary will be in uniform steps then the
volume of those posting will be O(n^2). Can't you just quote what's
necessary from the web-page?

Summary of sh/Bash Lecture:
===========================

Motivation:
-----------

----Fill In----

Basic Usage:
------------

- Executing simple commands: command name followed by parameters
    Examples: 
        ls
        ls -l
        cp test.pl old_test.pl

- Filename Matching mechanisms:
    * 
    []
    ?
    Examples:
        ls -l *.c
        cp *.c ./bak_dir
        
- Pipeline: explain a little about standard input/standard output, then show
    the following redirection mechanisms:
    |
    <
    Examples:
        ls -l | less
        cat *.c *h | wc -l
        ls -l | grep ^d | wc -l

- The ";" - executing more than one statements in the same batch. A 
    synchronous executions.
    Examples:
        cd ./test_dir ; tar -czvf ../test_dir.tar.gz *
    
- The "(" .. ")" - grouping statements inside a _subshell_ (separate process).
    Examples:
        ( cd ./bin ; ls d* ) > files_in_bin_that_start_with_a_d.txt

- The "{" .. "}" - grouping statement in the same shell (not a separate
  process).
    Examples:
        { cd ./bin ; ls d* } > files_in_bin_that_start_with_a_d.txt

- Using the backslash (with no whitespace afterwards) to split commands across
  several lines. Eases readability:
    Examples:
        cp *.c *.h README Makefile TODO \
            USAGE INSTALL \
                ./bak

- Introducing comments with "#". They start with a # and extend to the end of
  the line.
  
Variables:
----------

- Simple assignment: "=". (note that there cannot be any whitespace before
and after the "=" symbol.)
    Examples:
    A=hello
    B=yellow ; turn=500

- Retrieving the value of a variable using $ or ${} . (not $() !)
    Examples:
        - A=hello
          echo $A
        - VARIABLE=5
          B=${VARIABLE}
          VARIABLE=800
          echo $B
        - A=Y
          Y=80
          echo ${$A}
          
- A little about interpolation: A dollar can appear anywhere. If the shell
  encounters a $ which is not followed by curly brackets ("{" .. "}") it will
  try to interpolate its name from as many characters as it find, even if 
  a variable by that name does not exist. Thus, when in doubt, use the
  "${NAME}" form.

    Examples:
        - A=hello
          echo $Aworld
          # does not print helloworld

- The "${parameter:-defaultvalue}" form enables you to give the expression a 
  default value in case the variable is not assigned.
    Examples:
        -
            #!/bin/bash
            
            ; 
            ; Possibly set A
            B=${A:-not_set}
            ; Check if B is equal to not_set and accordingly do something.
            
- To unset a variable use the "unset" command:
    Examples:
        -
            #!/bin/bash
            A=5
            B=80
            RESULT=400
            echo $A \* $B = $RESULT
            unset A B RESULT

- To display a list of the declared variables and their values, use the "set"
  command without any options. (set is of little use in scripts except for
  debugging purposes).

  Examples:
     -
        A=32482 ; B=932840 ; C=1932840 ; D=890 ; E=hello ; F=world
        unset A E
        set | grep '^[A-F]='

- The "read VARNAME" command reads a line from the standard output and puts 
  it inside the variable "VARNAME". 
    Examples:
        echo "Please enter your name:"
        read NAME
        echo Hello $NAME

    - Note: Be careful not to use "read $VARNAME" when it's not appropriate.
        For example:
            #!/bin/sh
            A=B
            B=A
            read $A
            echo A is $A
            echo B is $B

Quoting, Backslashing and other animals
---------------------------------------

- A backslash before a character denotes an "actual" character. Hence means,
  it cannot be processed by the shell.
    Examples:
        - 
        echo Hello\ \ \ \ \ World        # vs.
        echo Hello     World
        -
        echo good ; echo you        
        echo good \; echo you                    # vs.
        -
        echo \\ - This is a backslash

- Use the double quotes to group strings which include whitespaces and
  keywords:
    Examples:
        echo "Hello   World"          # vs.
        echo Hello    World

    Note: double quotes do interpolation. For example:
        #!/bin/sh
        A=Hello
        echo "$A    world!"
        
- Use the single quotes to group strings which include whitespace, dollars
  and backslashes without doing variable interpolation:
    Examples:
        #!/bin/sh
        A=Hello
        echo '$A    world!'
        echo 'and here's a backslash - \'    # Note that \' is not considered
                                             # an inner single quote.

- Quotes and regular texts can be arbitrarily combined (but not nested !)
    Examples:
        #!/bin/sh
        myvar="young at heart"
        echo "Some pe"ople are "${myvar}".
        echo 'Me, 'included\!

Conditionals, Loops and Program Return Codes
--------------------------------------------

- Use the if statement to specify a conditional. Syntax:
    if <Test Command> ; then
        <If Block>
    elif <Test Command> ; then
        <El-If Block>
        .
        .
        .
    else
        <Else Block>
    fi

    As long as there are semi-colons the commands need not be on separate
    lines. Examples:
    
    -
        #!/bin/sh
        if test -e hello.txt ; then
            echo "hello.txt exists"
        else
            echo "hello.txt does not exist"
        fi
   
   Or the same on the same line:
        
        if test -e hello.txt ; then echo "hello.txt exists" ; else echo \
            "hello.txt does not exist" ; fi

   The latter syntax is useful for on-the-prompt scripting.
   
   -
        read A
        if expr $A \< 100 > /dev/null ; then   
            echo "$A is less than 100"
        fi

        # Note that we need to backslash the < so it won't be hijacked by the
        # shell, and if expr's output is not piped to /dev/null it will appear
        # on the screen

- Use the while loop to repeat a command as long as an expression is met.
    Syntax:
    while <Test Expression> ; do
        <Loop Block>
    done

    Examples:
    - 
        #!/bin/sh
        A=0
        while expr $A \< 100 > /dev/null ; do
            echo $A
            A=`expr $A + 1`    # The backticks can be used to trap the output
                               # of the command.
                               # More on that later.
        done
    
        This program prints the numbers from 0 to 99.

    - 
        #!/bin/sh
        find . -name '*.c' | 
        (while read T ; do
            cp $T $T.bak ;
        done)

        This program backups all the C files. read returns a false value when
        it encounters an EOF.

- Iterate over a group of values (or filenames) using the for command:
    for VARNAME in value1 value2 value3 ... ; do
        <For Block where you can use $VARNAME>
    done
    
    Examples:
    -    
        for I in *.c *.h ; do 
            cp $I $I.bak
        done

---TODO: a note about Program return codes, the $? variable, the true 
and false programs, and common program return codes ---

----------------------------------------------------------------------
Shlomi Fish        [email-masked] 
Home Page:         http://t2.technion.ac.il/~shlomif/
Home E-mail:       [email-masked]

The prefix "God Said" has the extraordinary logical property of 
converting any statement that follows it into a true one.

---

From: Omer Mussaev <[email-masked]>
Date: Mon, 06 Nov 2000 13:03:45 +0300

> necessary from the web-page?

----

${name#pattern}, ${name##pattern}, ${name%pattern} and ${name%%pattern}  
constructs:

${name#pattern} evaluates in following way:
pattern is expanded in path expanding way
shortest fit of beginning of name onto pattern is deleted
${name##pattern}
^shortest^longest
${name%%pattern}
^beginning^end
${name%pattern}
^longest^shortest

example:

for cppfile in *.cpp ; do mv ${cppfile} ${cppfile%cpp}C ; done

> Conditionals, Loops and Program Return Codes

--piping output of  loops:

for i in *.c ; do grep foo $i >/dev/null 2>&1 && echo $i ; done |  \
( echo "Files with \'foo\' pattern" ; while read filename ; do echo 
$filename ; done )

> and false programs, and common program return codes ---

and && and || constructs

> To unsubscribe from this group, send an email to:
> [email-masked]
> 
>