Программирование в 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