1. 結構化命令
(1)if-then語句
if command
then
commands
fi
示例:
#!/bin/bash
#testing multiple commands in the then section
testuser=root
if grep $testuser /etc/passwd
then
echo the bash files for user $testuser are:
ls -a /root/.b*
fi
grep是一個文本匹配命令。
(2)嵌套if語句
if command1
then
commands
elif command2
then
more commands
fi
示例:
#!/bin/bash
#testing the else section
testuser=badtest
if grep $testuser /etc/passwd
then
echo the files for user $testuser are:
ls -a /home/$testuser/.b*
else
echo "the user name $testuser doesn't exist on the system"
fi
(3)test命令
有兩種形式:
if test condition
then
commands
fi
與:
if [ condition ]
then
commands
fi
test命令主要是提供一種檢測if-then語句中不同條件的方法。如果test評估條件爲true,那麼test命令以狀態碼0退出。
數值比較:
n1 -eq n2 檢查n1是否等於n2
n1 -ge n2 檢查n1是否大於等於n2
n1 -gt n2 檢查n1是否大於n2
n1 -le n2 檢查n1是否小於等於n2
n1 -lt n2 檢查n1是否小於n2
n1 -ne n2 檢查n1是否等於n2
示例:
#!/bin/bash
#using numeric test comparsions
var11=10
var12=11
if [ $var11 -gt 5 ]
then
echo "the test value $var11 is greater than 5"
fi
if [ $var11 -eq $var12 ]
then
echo "the values are equal"
else
echo "the values are different"
fi
字符串比較:
str1=str2 檢查str1與str2是否相同
str1!=str2 檢查str1與str2是否不同
str1<str2 檢查str1是否小於str2
str1>str2 檢查str1是否大於str2
-n str1 檢查str1的長度是否大於0
-z str1 檢查str1的長度是否爲0
當比較一個字符串是大還是小時,一定要用轉義字符進行轉義,要不就當成重定向了。
示例:
#!/bin/bash
#>號會理解成重定向,因此需要轉義
var11=aeball
var12=hockey
if [ $var11/>$var12 ]
then
echo "$var11 is greater than $var12"
else
echo "$var11 is less than $var12"
fi
#!/bin/bash
va11=testing
va12=''
if [ -n $vall ]
then
echo "the string '$va11' is not empty"
else
echo "the string '$va11' is empty"
fi
if [ -z $va12 ]
then
echo "the string '$va12' is empty"
else
echo "the string '$va12'is not empty"
fi
if [ -z $va13 ]
then
echo "the string '$va13' is empty"
else
echo "the string $va13 is not empty"
fi
~
文件比較:
-d file 檢查file是否存在並且是一個目錄
-e file 檢查file是否存在
-f file 檢查file是否存在並且是一個文件
-r file 檢查file是否存在並且可讀
-s file 檢查file是否存在並且不爲空
-w file 檢查file是否存在並且可寫
-x file 檢查file是否存在並且可執行
-O file 檢查file是否存在並且被當前用戶擁有
-G file 檢查file是否存在並且默認組是否爲當前用戶組
file1 -nt file2 檢查file1是否比file2新
file1 -ot file2 檢查file1是否比file2舊
示例:
檢查目錄:
#!/bin/bash
#look before you leap
if [ -d $HOME ]
then
echo "your home directory exists"
cd $HOME
ls -a
else
echo "there's a problem with your HOME directory"
fi
檢查對象是否存在:
#!/bin/bash
#checking if a directory exists
if [ -e $HOME ]
then
echo "OK on the directory,now let's check the file"
if [ -e $HOME/testing ]
then
echo "Appending data to existing file"
date>>$HOME/testing
else
echo "creating new file"
date >$HOME/testing
fi
else
echo "sorry,you don't have a home directory"
fi
檢查文件:
#!/bin/bash
#check if a file
if [ -e $HOME ]
then
echo "the object exists,is it a file?"
if [ -f $HOME ]
then
echo "yes it's a file"
else
echo "no it's not a file"
if [ -f $HOME/.bash_profile ]
then
echo "but this is a file"
fi
fi
else
echo "sorry the object doesn't exist"
fi
檢查是否可讀:
#!/bin/bash
#testing if you can read a file
pwfile=/etc/shadow
if [ -f $pwfile ]
then
if [ -r $pwfile ]
then
tail $pwfile
else
echo "sorry,the ‘'$pwfile' can't read"
fi
else
echo "sorry,the $file doesn't exist"
fi
檢查文件是否爲空:
#!/bin/bash
#testing if a file is empty
file=test15
if [ -s $file ]
then
echo "the $file exists and has data in it"
var=`date'
else
echo "the $file exists and is empty"
fi
檢查文件是否可寫:
#!/bin/bash
#checking if a file is writeable
logfile=/home/t16test
touch $logfile
chmod u-w $logfile
now=`date +%y%m%d-%H%M`
if [ -w $logfile ]
then
echo "the program ran at: $now">$logfile
echo "the first attempt succeeded"
else
echo "the first attempt failed"
fi
chmod u+w $logfile
if [ -w $logfile ]
then
echo "the program ran at: $now">$logfile
echo "the second attempt succeeded"
else
echo "the second attempt failed"
fi
檢查文件是否可執行:
#!/bin/bash
#testing file execution
if [ -x test16 ]
then
echo "you can run the script"
./test16
else
echo "sorry,you can't execute the script"
fi
(4)複合條件查詢
if-then語句可以使用複合條件查詢。
if [ condition1 ] && [ condition2 ]
[ condition1 ] || [condition2 ]
示例:
#!/bin/bash
#testing compound comparsions
if [ -d $HOME ] && [ -w $/HOME/testing ]
then
echo "the file exists and you can write to it"
else
echo "I can't write to the file"
fi
(5) if-then的高級特徵
雙圓括號表示數學表達式。
雙方括號表示高級串處理函數
(( expression ))
expression可以是:
val++ 後增量
val-- 後減量
++val 前增量
--val 前減量
! 邏輯否定
~ 按位取反
** 取冪
<< 按位左移
>> 按位右移
[[ expression ]]
expression主要是與使用的標準字符串比較,提供了模式匹配的功能。
示例:
圓括號:
#!/bin/bash
#using double parenthesis
var1=10
if (( $var1**2>90 ))
then
((var2=$var1**2))
echo "the square of $var1 is $var2"
fi
方括號:
#!/bin/bash
#using pattern matching
if [[ $USER==r* ]]
then
echo "hello $USER"
else
echo "sorry,i don't know you"
fi
(6) case 命令
case命令格式:
case variable in
pattern1|pattern2) commands1;;
pattern3)commands2;;
*)default commands;;
esac
示例:
#!/bin/bash
#using the case command
case $USER in
rich|root)
echo "welcome,$USER"
echo "please enjoy your visit";;
testing)
echo "special testing account";;
jessica)
echo "don't forget to log off when you're done";;
*)
echo "sorry,you're not allowed here";;
esac
(7) for命令
格式:
for var in list
do
commands
done
讀取列表的值,然後進行迭代。
a.讀取列表中的簡單值:
#!/bin/bash
#basic for command
for test in Alabama Alaska Arizona Arkansas California Colorado
do
echo the nest state is $test
done
b.讀取列表中的複雜值:
#!/bin/bash
#another example of how not to user the for command
#當遇到單引號時,需要用雙引號,或者用/轉 義
for test in I don/'t know if "this'll" work
do
echo "word:$test"
done
分析:在上面的腳本中遇到了單引號,don't與this'll必須進行轉義或者是用雙引號。
#!/bin/bash
#for 命令是用空格來分隔列表中的值,然後當個別數值中有空格時,應當用雙引號包圍
for test in Nevadaw "New York" "New Mexico"
do
echo "Now going to $test"
done
分析:for命令默認是用空格來分割,如果個別值中有空格時,應當用雙引號包圍起來。
c.讀取命令中的值:
#!/bin/bash
#reading values from a file
file="states"
for state in `cat $file`
do
echo "visit beautiful $state"
done
分析: cat $file用的是反引號。
d.改變字段分割符:
默認情況下,shell將空格,製表符,換行符看成是字段分割符。
如果把字段分割符IFS更改爲換行符,則IFS=$'/n'
#!/bin/bash
#改變字段分隔符,bash shell的字符分隔符有以下幾種: 空格,製表符,換行符
file="states"
IFS=$'/n'
for state in `cat $file`
do
echo "visit beautiful $state"
done
IFS=$IFS.OLD #還原內部字段分隔符
e.使用通配符讀取目錄:
#!/bin/bash
#interate through all the files in a directory
for file in /home/*
do
if [ -d "$file" ]
then
echo $file is a dir
elif [ -f "$file" ]
then
echo "$file is a file"
fi
done
(8)C 式for命令
格式:
for (( a=1;a<10;a++ ))
單個變量:
#!/bin/bash
#testing the C-style for loop
for ((i=1;i<=10;i++))
do
echo "the next number is $i"
done
多個變量:
#!/bin/bash
#multiple variables
for ((a=1,b=10;a<=10;a++,b--))
do
echo "$a-$b"
done
(9) while命令
格式:
while test command
do
other commands
done
#!/bin/bash
#while command test
var1=10
while [ $var1 -gt 0 ]
do
echo $var1
var1=$[ $var1-1 ]
done
#!/bin/bash
#testing a multicommand while loop
var1=10
while echo $var1
[ $var1 -ge 0 ]
do
echo "this is inside the loop"
var1=$[ $var1-1 ]
done
分析:兩條測試命令,一條是 echo $var1,另一條是 [ $var1 -ge 0 ]
2. 命令行參數
(1)讀取參數
向shell腳本傳遞數據最基本的使用命令行參數(command line parameters).
$0 表示程序名稱 $1表示第一個參數 $2表示第二個參數 ..... $9表示第9個參數
如果使用第10個參數就用 ${10}
#!/bin/bash
#using one command line parameter
factorial=1
for ((number=1;number<=$1;number++))
do
factorial=$[ $factorial*$number ]
done
echo the factorial of $1 is $factorial
./test1 5
(2)讀取程序名稱
basename只返回程序名稱,不帶路徑。
#!/bin/bash
#testing a multi-function script
name=`basename $0`
if [ $name="addem" ]
then
total=$[ $1+$2 ]
elif [ $name="multem" ]
then
total=$[ $1*$2 ]
fi
echo the caculated value is $total
(3) 參數計數
$#存儲的是包含命令行參數的個數。
#!/bin/bash
if [ $# -ne 2 ]
then
echo Usage:test9 a b
else
total=$[ $1+$2 ]
echo the total is $total
fi
#!/bin/bash
#grabbing the last parameter
params=$#
echo the last param is $params
echo the last parameter is ${!#}
${!#}得到最後個命令行參數的值。
當沒有任何參數時,即$#等於0,那麼${!#}將返回腳本的名稱。
(4)獲取所有數據
$* 把命令行提供的所有參數當成一個單詞處理。
$@ 把命令行提供的所有參數當成同一個字符串中的多個單詞進行處理。
#!/bin/bash
#獲得所有數據
#testing s* and S@
count=1
for param in "$*"
do
echo "/S* parameter #$count=$param"
count=$[ $count+1 ]
done
count=1
for param in "$@"
do
echo "/$@ parameter #$count=$param"
count=$[ $count+1 ]
done
結果:
[root@localhost chapter11]# ./test11 a b c d e
/S* parameter #1=a b c d e
$@ parameter #1=a
$@ parameter #2=b
$@ parameter #3=c
$@ parameter #4=d
$@ parameter #5=e
3. 獲取用戶輸入
read命令接收標準的鍵盤讀入.
(1)基本讀取
#!/bin/bash
#testing the read -p option
read -p "please enter your age:" age
days=$[ $age*365 ]
echo "that makes you over $days days old!"
read -p允許在命令行中直接指定一個提示。
[root@localhost chapter11]# ./test22
please enter your age:10
that makes you over 3650 days old!
如果不指定變量,那麼read命令將數據接收到環境變量REPLY中去。
#!/bin/bash
#testing the REPLY environment variable
read -p "Enter a number:"
factorial=1
for ((count=1;count<=$REPLY;count++))
do
factorial=$[ $factorial*$count ]
done
echo "the factorial of $REPLY is $factorial"
(2)計時
read命令,腳本會停止下來等待輸入,可以指定一定的時間,當超過這個時間後,繼續執行後面的腳本。
read -t
#!/bin/bash
#timing the data entry
if read -t 5 -p "please enter your name:" name
then
echo "hello $name,welcome to my script"
else
echo
echo "sorry ,two slow"
fi
~
分析:當超過5秒不輸入時,自動執行後面的腳本。
read -n1 表示接收到1個字符就退出。
#!/bin/bash
#getting just one character of input
read -n1 -p "Do you want to continue[Y/N]?" answer
case $answer in
Y|y)echo
echo "fine,continue on....";;
N|n)echo
echo Ok,goodbye
exit;;
esac
echo "this is the end of the script"
(3)默讀
當用戶的輸入不顯示在顯示器上,即把文本顏色設置成背景顏色即可。 read -s
#!/bin/bash
#hiding input data from the monitor
read -s -p "Enter your password:" pass
echo
echo "Is your password really $pass?"
(4)讀取文件
即從文件中讀取數據,
#!/bin/bash
#reading data from a file
#通過管道將數據送給read命令
count=1
cat /etc/passwd|while read line
do
echo "Line $count:$line"
count=$[ $count+1 ]
done
總結:這篇文章主要shell腳本的一些基本結構化命令,如if,for,while.以及命令行參數,$1,$2,$#,$*,$@.最後還有讀取用戶輸入命令read.
接下來的文章主要介紹shell高級編程部分,包括正則表達式,sed,gawk.