shell腳本語言編程

#Shell既是一種命令語言,又是一種程序設計語言,作爲命令語言,它交互式地解釋和執行用戶輸入的命令;作爲程序設計語言,它定義了各種變量和參數,並提供了許多在高級語言中才具有的控制結構,包括循環和分支


#--------------shell 變量-------------------
#變量名和等號之間不能有空格
 #首個字符必須爲字母(a-z,A-Z)。
#中間不能有空格,可以使用下劃線(_)。
#不能使用標點符號。
#不能使用bash裏的關鍵字(可用help命令查看保留關鍵字)
#使用一個定義過的變量,只要在變量名前面加美元符號($)即可,變量名外面的花括號是可選的,加不加都行,加花括號是爲了幫助解釋器識別變量的邊界
#使用 readonly 命令可以將變量定義爲只讀變量
#使用 unset 命令可以刪除變量


#$0 當前腳本的文件名  $n 傳遞給腳本或函數的參數   $# 傳遞給腳本或函數的參數個數   $*/$@ 傳遞給腳本或函數的所有參數    $? 上個命令的退出狀態,或函數的返回值  $$ 當前Shell進程ID
#$* 和 $@ 的區別:但是當它們被雙引號(" ")包含時,"$*" 會將所有的參數作爲一個整體,以"$1 $2 … $n"的形式輸出所有參數;"$@" 會將各個參數分開,以"$1" "$2" … "$n" 的形式輸出所有參數
#\\ 反斜槓     \b 退格(刪除鍵)  \n 換行   \r 回車   \t 水平製表符(tab鍵)  \v 垂直製表符


#變量替換可以根據變量的狀態(是否爲空、是否定義等)來改變它的值
#${var:-word} 如果變量 var 爲空或已被刪除(unset),那麼返回 word,但不改變 var 的值    ${var:=word} 如果變量 var 爲空或已被刪除(unset),那麼返回 word,並將 var 的值設置爲 word    ${var:+word} 如果變量 var 被定義,那麼返回 word,但不改變 var 的值
# ${var:?message} 如果變量 var 爲空或已被刪除(unset),那麼將消息 message 送到標準錯誤輸出,可以用來檢測變量 var 是否可以被正常賦值。若此替換出現在Shell腳本中,那麼腳本將停止運


#命令替換的語法:`command`
#--------------shell 變量-------------------

#!/bin/bash


echo "what is your name?"
read P
echo "Hello,$P"


#運算符
#1.expr能完成表達式的求值操作,表達式和運算符之間要有空格,比如2 + 2,完整的表達式要被` `包含 ,變量與=之間不能有空格,乘號(*)前邊必須加反斜槓(\)才能實現乘法運算;
a=10
b=20


val=`expr $a + $b`                     
echo "a + b: $val"


val=`expr $a - $b`
echo "a - b : $val"


val=`expr $a \* $b`
echo  "a * b: $val"


val=`expr $a / $b`
echo "a / b : $val"


val=`expr $b % $a`
echo "b % a : $val"


#條件表達式要放在方括號之間,並且要有空格,例如 [$a==$b] 是錯誤的,必須寫成 [ $a == $b ]
if [ $a == $b ]
then
  echo "a is equal to b"
 fi
 
 if [ $a !=  $b ]
 then
   echo "a is not equal to b"
  fi
  
  
  #關係運算符
  #只支持數字,不支持字符串,除非字符串的值是數字。
  #-eq 檢測兩個數是否相等,相等返回true.   -ne檢測兩個數是否相等,不相等返回true.    -gt或-ge檢測左邊數是否大於右邊  -lt或-le檢測左邊數是否小於右邊
  if [ $a -eq $b ]
  then
  echo "true"
  else
  echo "false"
  fi
  
  # !非運算,[!false]返回true,   -o或運算,有一個爲true,則返回true,   -a與運算,兩個都爲true,才返回true
  if [ $a -lt 100 -a $b -gt 15 ]
  then 
  echo "true"
  else
  echo "false"
  fi
  
  #字符串運算符
  # -z 檢測字符串長度是否爲0,爲0返回 true. -n檢測字符串長度是否爲0,不爲0返回 true. str檢測字符串長度是否爲空,不爲空返回true.
  c="abc"
  d="def"
  if [ -z $a -a -z $b ]
  then 
  echo "ture"
  else
  echo "false"
  fi


#文件測試運算符
# -b(塊設備文件,是則返回true).-c(字符設備文件.是則返回true).-d(是否是目錄,是則返回true). -f(普通文件).-g(是否設置SGID位).-k(是否設置粘着位).
# -p(是否具名管道).-u(是否設置SUID位).-r(是否可讀),-w(是否可寫).-x(是否可執行).-s(是否爲空.文件大小是否大於0,不爲空返回true).-e(文件(包括目錄)是否存在)
file="/F/work_sources/study_resources/shell.sh"
if [ -r $file ]
then echo "read"
else echo "not read"
fi


#shell註釋  可以把要註釋的代碼用一對花括號括起來,定義成函數.


#shell字符串可以用單引號,也可以用雙引號,也可以不用引號.
#單引號裏的任何字符都會原樣輸出,單引號字符串中的變量是無效的.單引號字串中不能出現單引號(對單引號使用轉義符後也不行)
#雙引號裏可以有變量.雙引號裏可以出現轉義字符
name="xx"
str="hello,i know you are\"$name\"! "
echo $str


#獲取字符串長度
string="avsss"
echo ${#string}


#提取字符串
string="ali is a great company"
echo ${string:1:10}


#查找子字符串
string="ali is a great company"
echo `expr index "$string" is`


#數組
#bash支持一維數組(不支持多維數組).Shell中,用括號來表示數組,數組元素用“空格”符號分割開
array_name=(value0 value1 value2 value3)
#讀取數組,使用@ 或 * 可以獲取數組中的所有元素
echo ${array_name[2]}
#獲取數組的長度
echo "length=${#array_name[*]}“
echo "length=${#array_name[@]}"


#echo命令
#雙引號可有可無,單引號主要用在原樣輸出中, 換行(\n),不換行(\c)
echo `date`
#顯示結果重定向至文件     echo "It is a test" > myfile                 若需要原樣輸出字符串(不進行轉義),請使用單引號     echo '$name\"'


#printf 命令用於格式化輸出, 是echo命令的增強版,printf 不像 echo 那樣會自動換行,必須顯式添加換行符(\n)             printf 命令的語法:printf  format-string  [arguments...]format-string 爲格式控制字符串,arguments 爲參數列表
printf "hello!\n"


#
    if ..then. fi 語句;
    if ..then. else .then.. fi 語句;
    if ..then. elif .then.. else .then.. fi 語句。


# test 命令用於檢查某個條件是否成立,與方括號([ ])類似。
    if test $[2*3] -eq $[1+5]; then echo 'The two numbers are equal!'; fi;


 function file(){
option="${1}"
case ${option} in
   -f) FILE="${2}"
      echo "File name is $FILE"
      ;;
   -d) DIR="${2}"
      echo "Dir name is $DIR"
      ;;
   *) 
      echo "`basename ${0}`:usage: [-f file] | [-d directory]"
      exit 1 # Command to come out of the program with status 1   
      ;;
esac
}


function  about(){
case 值 in
模式1)
    command1
    command2
    command3
    ;;
模式2)
    command1
    command2
    command3
    ;;
*)
    command1
    command2
    command3
    ;;
esac




for循環一般格式爲:
for 變量 in 列表      列表是一組值(數字、字符串等)組成的序列,每個值通過空格分隔。每循環一次,就將列表中的下一個值賦給變量,in 列表是可選的,如果不用它,for 循環使用命令行的位置參數
do
    command1
    command2
    ...
    commandN
done


顯示主目錄下以 .bash 開頭的文件:


for FILE in $HOME/.bash*
do
   echo $FILE
done


while循環用於不斷執行一系列命令,也用於從輸入文件中讀取數據;命令通常爲測試條件。其格式爲:


while 判斷條件
do
   Statement
done
}
 #while循環可用於讀取鍵盤信息。下面的例子中,輸入信息被設置爲變量FILM,按<Ctrl-D>結束循環 
echo 'type <CTRL-D> to terminate'
echo -n 'enter your most liked film: '
while read FILM
do
    echo "Yeah! great film the $FILM"
done    

#until 循環執行一系列命令直至條件爲 true 時停止
a=0
until [ ! $a -lt 10 ]
do
   echo $a
   a=`expr $a + 1`
done


#shell 跳出循環 
#break命令允許跳出所有循環(終止執行後面的所有循環).在嵌套循環中,break 命令後面還可以跟一個整數,表示跳出第幾層循環
#continue命令與break命令類似,只有一點差別,它不會跳出所有循環,僅僅跳出當前循環,continue 後面也可以跟一個數字,表示跳出第幾層循環


#Shell 函數的定義格式
#function_name(){}       函數返回值,可以顯式增加return語句;如果不加,會將最後一條命令運行結果作爲返回值.Shell 函數返回值只能是整數,一般用來表示函數執行成功與否,0表示成功,其他值表示失敗
# Define your function here
Hello () {
   echo "Url is http://see.xidian.edu.cn/cpp/shell/"
}
# Invoke your function
#Hello     調用函數只需要給出函數名,不需要加括號
#unset .f function_name   刪除函數也可以使用 unset 命令,不過要加上 .f 選項
#如果你希望直接從終端調用函數,可以將函數定義在主目錄下的 .profile 文件,這樣每次登錄後,在命令提示符後面輸入函數名字就可以立即調用


在Shell中,調用函數時可以向其傳遞參數。在函數體內部,通過 $n 的形式來獲取參數的值,例如,$1表示第一個參數,$2表示第二個參數.
#注意,$10 不能獲取第十個參數,獲取第十個參數需要${10}。當n>=10時,需要使用${n}來獲取參數
funWithParam(){
    echo "The value of the first parameter is $1 !"
    echo "The value of the second parameter is $2 !"
    echo "The value of the tenth parameter is $10 !"
    echo "The value of the tenth parameter is ${10} !"
    echo "The value of the eleventh parameter is ${11} !"
    echo "The amount of the parameters is $# !"  # 參數個數
    echo "The string of the parameters is $* !"  # 傳遞給函數的所有參數
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73


#  $# 傳遞給函數的參數個數。 $* 顯示所有傳遞給函數的參數。 $? 函數的返回值.




#Shell  輸入輸出重定向
     #注意:輸出重定向是大於號(>),輸入重定向是小於號(<)
     #命令的輸出不僅可以是顯示器,還可以很容易的轉移到文件,這被稱爲輸出重定向
     #command > file   (輸出到顯示器的內容就可以被重定向到文件) 如果不希望文件內容被覆蓋,可以使用 >> 追加到文件末尾
     for i in 1 2 3
     do
     echo "$i">>test.txt
     done


#一般情況下,每個 Unix/Linux 命令運行時都會打開三個文件:
 #標準輸入文件(stdin):stdin的文件描述符爲0,Unix程序默認從stdin讀取數據。
  #標準輸出文件(stdout):stdout 的文件描述符爲1,Unix程序默認向stdout輸出數據。
  #標準錯誤文件(stderr):stderr的文件描述符爲2,Unix程序會向stderr流中寫入錯誤信息。
  #默認情況下,command > file 將 stdout 重定向到 file,command < file 將stdin 重定向到 file
    #   $command > file 2>&1    (stdout 和 stderr 合併後重定向到 file)       $command < file1 >file2  (對 stdin 和 stdout 都重定向)
    # n >& m 將輸出文件 m 和 n 合併。
    # n <& m 將輸入文件 m 和 n 合併。
    # << tag 將開始標記 tag 和結束標記 tag 之間的內容作爲輸入。
    
    #  wc -l 命令計算 document 的行數
    #Here Document "嵌入文檔" ,是 Shell 中的一種特殊的重定向方式
cat << EOF
This is a simple lookup program
for good (and bad) restaurants
in Cape Town.
EOF


 # command > /dev/null      (/dev/null 是一個特殊的文件,寫入到它的內容都會被丟棄;如果嘗試從該文件讀取內容,那麼什麼也讀不到。但是 /dev/null 文件非常有用,將命令的輸出重定向到它,會起到”禁止輸出“的效果。)




#Shell 也可以包含外部腳本,將外部腳本的內容合併到當前腳本
#可以使用 . filename 或source filename     一般使用點號(.),但是注意點號(.)和文件名中間有一空格   注意:被包含腳本不需要有執行權限


#touch命令主要用來修改文件時間戳,或者新建一個不存在的文件




#sed命令(sed是一個很好的文件處理工具,本身是一個管道命令,主要是以行爲單位進行處理,可以將數據行進行替換、刪除、新增、選取等特定工作)
     #sed命令行格式爲:     sed [-nefri] ‘command’ 輸入文本  
     sed(){
-i:直接修改源文件  sed -i 's/123/234/' test.sh   將文件 test.sh內出現的“123”替換爲“234”
-e:多次編輯  sed -i -e 's/123/234/g' -i -e '7 s/^/#/' test.sh  先將所有的123替換爲234,再將第7行前加#號註釋
-f:指定sed腳本文件名
-n:取消默認的輸出,用sed不加任何選項的話你會看到所有內容輸出,並不是按照sed命令所限制的條件輸出
sed -n '2p' test.txt  顯示第2行的內容   sed -n '1p' test.txt 第一行   sed -n '$p' test.txt 最後一行
sed -n '1,3'p test.txt 顯示第1到3行的內容
sed -n '/val/'p test.txt 僅顯示包含“val”字符的行
sed -n '/\$/'p test.txt 顯示包含"$"字符的行
sed -n '/[0-9]$/'p test.txt 顯示以數字結尾的行,[0-9]是正則表達式 代表數字0到9;"$"表示行尾(“^”表示行首)
sed -n -e '/^T/'p -e '/[0-9]$/'p test.txt 顯示以數字結尾的行並顯示以大寫T爲開頭的行
sed -n '/.*ing/'p test.txt 顯示含“ing”的行
sed -n 's/nurse/little &/p' test.txt  將“nurse”改爲“little nurse”,“&”命令用來重新調用被替換的內容
sed 's/--*//g' | sed '/^$/d' | sed '$d' | sed '1d' | awk '{print $1}' 使用s/--*//g刪除橫線-------     使用/^$/d刪除空行 使用$d刪除最後一行 使用1d刪除第一行      awk {print $1}打印第一列
sed -i -e 's/^/#&/' test.txt 給每行行首加上“#”註釋
}
 
#‘grep’是一種強大的文本搜索工具,它能使用正則表達式搜索文本,並把匹配的行打印出來
grep(){
結合使用"^$"查詢空行
\< 和 \> 分別標註單詞的開始與結尾
-c   只輸出匹配行的計數
-i   不區分大小寫
-h   查詢多文件時不顯示文件名
-l   只列出匹配的文件名
 -L 列出不匹配的文件名
-n   顯示匹配行及行號
-v   反向選擇,顯示不包含匹配文本的所有行
-w 只匹配整個單詞
-r     遞歸搜索,不僅搜索當前工作目錄,而且搜索子目錄
--color=auto :可以將找到的關鍵詞部分加上顏色的顯示喔!(在 ~/.bashrc 內加上這行:alias grep='grep --color=auto'再以『source ~/.bashrc 來立即生效, 這樣每次運行 grep 他都會自動幫你加上顏色顯示啦)
 grep -l -r ‘energywise’ * #在當前目錄及其子目錄下搜索'energywise'行的文件,但是不顯示匹配的行,只顯示匹配的文件
}
 
readlink (){
readlink -f  判斷執行文件的類型,如果是一個符號鏈接,得到這個鏈接的目的路徑
}
xargs(){
管道符後不加xargs相當於先將管道後面的命令回車執行一下,再從鍵盤裏輸入管道符前面命令執行的結果內容;加上xargs 相當於直接從鍵盤輸入管道符前面命令執行的結果內容再回車
}

tr命令可以對來自標準輸入的字符進行替換、壓縮和刪除

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章