Программирование в BASH

 

sample1.sh

#!/bin/bash

 

#  Tip:

#  If you're unsure how a certain condition might evaluate,

#+ test it in an if-test.

 

echo

 

echo "Testing \"0\""

if [ 0 ]      # zero

then

  echo "0 is true."

else          # Or else ...

  echo "0 is false."

fi            # 0 is true.

 

echo

 

echo "Testing \"1\""

if [ 1 ]      # one

then

  echo "1 is true."

else

  echo "1 is false."

fi            # 1 is true.

 

echo

 

echo "Testing \"-1\""

if [ -1 ]     # minus one

then

  echo "-1 is true."

else

  echo "-1 is false."

fi            # -1 is true.

 

echo

 

echo "Testing \"NULL\""

if [ ]        # NULL (empty condition)

then

  echo "NULL is true."

else

  echo "NULL is false."

fi            # NULL is false.

 

echo

 

echo "Testing \"xyz\""

if [ xyz ]    # string

then

  echo "Random string is true."

else

  echo "Random string is false."

fi            # Random string is true.

 

echo

 

echo "Testing \"\$xyz\""

if [ $xyz ]   # Tests if $xyz is null, but...

              # it's only an uninitialized variable.

then

  echo "Uninitialized variable is true."

else

  echo "Uninitialized variable is false."

fi            # Uninitialized variable is false.

 

echo

 

echo "Testing \"-n \$xyz\""

if [ -n "$xyz" ]            # More pedantically correct.

then

  echo "Uninitialized variable is true."

else

  echo "Uninitialized variable is false."

fi            # Uninitialized variable is false.

 

echo

 

 

xyz=          # Initialized, but set to null value.

 

echo "Testing \"-n \$xyz\""

if [ -n "$xyz" ]

then

  echo "Null variable is true."

else

  echo "Null variable is false."

fi            # Null variable is false.

 

 

echo

 

 

# When is "false" true?

 

echo "Testing \"false\""

if [ "false" ]              #  It seems that "false" is just a string ...

then

  echo "\"false\" is true." #+ and it tests true.

else

  echo "\"false\" is false."

fi            # "false" is true.

 

echo

 

echo "Testing \"\$false\""  # Again, uninitialized variable.

if [ "$false" ]

then

  echo "\"\$false\" is true."

else

  echo "\"\$false\" is false."

fi            # "$false" is false.

              # Now, we get the expected result.

 

#  What would happen if we tested the uninitialized variable "$true"?

 

echo

 

exit 0

sample2.sh

#!/bin/bash

a=3

 

if [ "$a" -gt 0 ]

then

  if [ "$a" -lt 5 ]

  then

    echo "The value of \"a\" lies somewhere between 0 and 5."

  fi

fi

 

# Same result as:

 

if [ "$a" -gt 0 ] && [ "$a" -lt 5 ]

then

  echo "The value of \"a\" lies somewhere between 0 and 5."

fi

exit

sample3.sh

#!/bin/bash

# Counting to 11 in 10 different ways.

 

n=1; echo -n "$n "

 

let "n = $n + 1"   # let "n = n + 1"  also works.

echo -n "$n "

 

 

: $((n = $n + 1))

#  ":" necessary because otherwise Bash attempts

#+ to interpret "$((n = $n + 1))" as a command.

echo -n "$n "

 

(( n = n + 1 ))

#  A simpler alternative to the method above.

 

echo -n "$n "

 

n=$(($n + 1))

echo -n "$n "

 

: $[ n = $n + 1 ]

#  ":" necessary because otherwise Bash attempts

#+ to interpret "$[ n = $n + 1 ]" as a command.

#  Works even if "n" was initialized as a string.

echo -n "$n "

 

n=$[ $n + 1 ]

#  Works even if "n" was initialized as a string.

#* Avoid this type of construct, since it is obsolete and nonportable.

 

echo -n "$n "

 

# Now for C-style increment operators.

 

let "n++"          # let "++n"  also works.

echo -n "$n "

 

(( n++ ))          # (( ++n ))  also works.

echo -n "$n "

 

: $(( n++ ))       # : $(( ++n )) also works.

echo -n "$n "

 

: $[ n++ ]         # : $[ ++n ] also works

echo -n "$n "

 

echo

 

exit 0

sample4.sh

#!/bin/bash

# Multiple ways to count up to 10.

 

echo

 

# Standard syntax.

for a in 1 2 3 4 5 6 7 8 9 10

do

  echo -n "$a "

done  

 

echo; echo

 

# +==========================================+

 

# Using "seq" ...

for a in `seq 10`

do

  echo -n "$a "

done  

 

echo; echo

 

# +==========================================+

 

# Using brace expansion ...

# Bash, version 3+.

for a in {1..10}

do

  echo -n "$a "

done  

 

echo; echo

 

# +==========================================+

 

# Now, let's do the same, using C-like syntax.

 

LIMIT=10

 

for ((a=1; a <= LIMIT ; a++))  # Double parentheses, and naked "LIMIT"

do

  echo -n "$a "

done                           # A construct borrowed from ksh93.

 

echo; echo

 

# +=========================================================================+

 

# Let's use the C "comma operator" to increment two variables simultaneously.

 

for ((a=1, b=1; a <= LIMIT ; a++, b++))

do  # The comma concatenates operations.

  echo -n "$a-$b "

done

 

echo; echo

 

exit 0

sample5.sh

#!/bin/bash

# wh-loopc.sh: Count to 10 in a "while" loop.

 

LIMIT=10                 # 10 iterations.

a=1

 

while [ "$a" -le $LIMIT ]

do

  echo -n "$a "

  let "a+=1"

done                     # No surprises, so far.

 

echo; echo

 

# +=================================================================+

 

# Now, we'll repeat with C-like syntax.

 

((a = 1))      # a=1

# Double parentheses permit space when setting a variable, as in C.

 

while (( a <= LIMIT ))   #  Double parentheses,

do                       #+ and no "$" preceding variables.

  echo -n "$a "

  ((a += 1))             # let "a+=1"

  # Yes, indeed.

  # Double parentheses permit incrementing a variable with C-like syntax.

done

 

echo

 

# C and Java programmers can feel right at home in Bash.

 

exit 0

sample6.sh

#!/bin/bash

 

END_CONDITION=end

 

until [ "$var1" = "$END_CONDITION" ]

# Tests condition here, at top of loop.

do

  echo "Input variable #1 "

  echo "($END_CONDITION to exit)"

  read var1

  echo "variable #1 = $var1"

  echo

done  

 

# ------------------------------------------- #

 

#  As with "for" and "while" loops,

#+ an "until" loop permits C-like test constructs.

 

LIMIT=10

var=0

 

until (( var > LIMIT ))

do  # ^^ ^     ^     ^^   No brackets, no $ prefixing variables.

  echo -n "$var "

  (( var++ ))

done    # 0 1 2 3 4 5 6 7 8 9 10

 

 

exit 0

sample7.sh

#!/bin/bash

# numbers.sh: Representation of numbers in different bases.

 

# Decimal: the default

let "dec = 32"

echo "decimal number = $dec"             # 32

# Nothing out of the ordinary here.

 

 

# Octal: numbers preceded by '0' (zero)

let "oct = 032"

echo "octal number = $oct"               # 26

# Expresses result in decimal.

# --------- ------ -- -------

 

 

# Hexadecimal: numbers preceded by '0x' or '0X'

let "hex = 0x32"

echo "hexadecimal number = $hex"         # 50

 

echo $((0x9abc))                         # 39612

#     ^^      ^^   double-parentheses arithmetic expansion/evaluation

# Expresses result in decimal.

 

 

 

# Other bases: BASE#NUMBER

# BASE between 2 and 64.

# NUMBER must use symbols within the BASE range, see below.

 

 

let "bin = 2#111100111001101"

echo "binary number = $bin"              # 31181

 

let "b32 = 32#77"

echo "base-32 number = $b32"             # 231

 

let "b64 = 64#@_"

echo "base-64 number = $b64"             # 4031

# This notation only works for a limited range (2 - 64) of ASCII characters.

# 10 digits + 26 lowercase characters + 26 uppercase characters + @ + _

 

 

echo

 

echo $((36#zz)) $((2#10101010)) $((16#AF16)) $((53#1aA))

                                         # 1295 170 44822 3375

 

 

#  Important note:

#  --------------

#  Using a digit out of range of the specified base notation

#+ gives an error message.

 

let "bad_oct = 081"

# (Partial) error message output:

#  bad_oct = 081: value too great for base (error token is "081")

#              Octal numbers use only digits in the range 0 - 7.

 

exit $?   # Exit value = 1 (error)

sample8.sh

#!/bin/bash

# c-vars.sh

# Manipulating a variable, C-style, using the (( ... )) construct.

 

 

echo

 

(( a = 23 ))  #  Setting a value, C-style,

              #+ with spaces on both sides of the "=".

echo "a (initial value) = $a"   # 23

 

(( a++ ))     #  Post-increment 'a', C-style.

echo "a (after a++) = $a"       # 24

 

(( a-- ))     #  Post-decrement 'a', C-style.

echo "a (after a--) = $a"       # 23

 

 

(( ++a ))     #  Pre-increment 'a', C-style.

echo "a (after ++a) = $a"       # 24

 

(( --a ))     #  Pre-decrement 'a', C-style.

echo "a (after --a) = $a"       # 23

 

echo

 

########################################################

#  Note that, as in C, pre- and post-decrement operators

#+ have different side-effects.

 

n=1; let --n && echo "True" || echo "False"  # False

n=1; let n-- && echo "True" || echo "False"  # True

 

########################################################

 

echo

 

(( t = a<45?7:11 ))   # C-style trinary operator.

#       ^  ^ ^

echo "If a < 45, then t = 7, else t = 11."  # a = 23

echo "t = $t "                              # t = 7

 

echo

 

# These work only with version 2.04 or later of Bash.

 

exit

sample9.sh

#!/bin/bash

# printf demo

 

declare -r PI=3.14159265358979     # Read-only variable, i.e., a constant.

declare -r DecimalConstant=31373

 

Message1="Greetings,"

Message2="Earthling."

 

echo

 

printf "Pi to 2 decimal places = %1.2f" $PI

echo

printf "Pi to 9 decimal places = %1.9f" $PI  # It even rounds off correctly.

 

printf "\n"                                  # Prints a line feed,

                                             # Equivalent to 'echo' . . .

 

printf "Constant = \t%d\n" $DecimalConstant  # Inserts tab (\t).

 

printf "%s %s \n" $Message1 $Message2

 

echo

 

# ==========================================#

# Simulation of C function, sprintf().

# Loading a variable with a formatted string.

 

echo

 

Pi12=$(printf "%1.12f" $PI)

echo "Pi to 12 decimal places = $Pi12"      # Roundoff error!

 

Msg=`printf "%s %s \n" $Message1 $Message2`

echo $Msg; echo $Msg

 

#  As it happens, the 'sprintf' function can now be accessed

#+ as a loadable module to Bash,

#+ but this is not portable.

 

exit 0

sample10.sh

#! /bin/bash

 

 

while [ $# -gt 0 ]; do    # Until you run out of parameters . . .

  case "$1" in

    -d|--debug)

              # "-d" or "--debug" parameter?

              DEBUG=1

              ;;

    -c|--conf)

              CONFFILE="$2"

              shift

              if [ ! -f $CONFFILE ]; then

                echo "Error: Supplied file doesn't exist!"

                exit $E_CONFFILE     # File not found error.

              fi

              ;;

  esac

  shift       # Check next set of parameters.

done