shell編程筆記

########認識shell
1.Unix/Linux上常見的Shell腳本解釋器有bash、sh、csh、ksh等,習慣上把它們稱作一種Shell。我們常說有多少種Shell,其實說的是Shell腳本解釋器。
注意:bash是 Bourne Again Shell 的縮寫,是linux標準的默認shell ,它基於Bourne shell,吸收了C shell和Korn shell的一些特性。bash完全兼容sh,也就是說,用sh寫的腳本可以不加修改的在bash中執行。

2.#!/bin/bash
“#!” 是一個約定的標記,它告訴系統這個腳本需要什麼解釋器來執行,即使用哪一種Shell。echo命令用於向窗口輸出文本。

3.chmod +x ./test.sh腳本添加執行權限
注意,一定要寫成./test.sh,而不是test.sh。運行其它二進制的程序也一樣,直接寫test.sh,linux系統會去PATH裏尋找有沒有叫test.sh的,而只有/bin, /sbin, /usr/bin,/usr/sbin等在PATH裏,你的當前目錄通常不在PATH裏,所以寫成test.sh是會找不到命令的,要用./test.sh告訴系統說,就在當前目錄找。

4.read 命令從stdin獲取輸入並賦值給Person變量,最後在stdout上輸出:
#!/bin/bash

#Author:HJY
#Script follows here:[email protected]:/root

echo "What's your name?"
read Person
echo "Hello,$Person"

########shell變量
1.myNum=8
注意,變量名和等號之間不能有空格

2.使用一個定義過的變量,只要在變量名前面加美元符號($)即可
 my_name="hjy"
 echo $my_name
 echo ${my_name}
變量名外面的花括號是可選的,加不加都行,加花括號是爲了幫助解釋器識別變量的邊界

3.已定義的變量,可以被重新定義
 myUrl="http://see.xidian.edu.cn/cpp/linux/"
 echo ${myUrl}
 myUrl="http://see.xidian.edu.cn/cpp/shell/"
 echo ${myUrl}

4.使用 readonly 命令可以將變量定義爲只讀變量,只讀變量的值不能被改變。

5.使用 unset 命令可以刪除變量。語法:
 unset variable_name
變量被刪除後不能再次使用;unset 命令不能刪除只讀變量

########shell特殊變量
1.包含其他字符的變量有特殊含義,稱爲特殊變量。
 $0:當前腳本的文件名
 $n:傳遞給腳本或函數的參數。n是一個數字,表示第幾個參數。例如,第一個參數是$1,第二個參數是$2。
 $#:傳遞給腳本或函數的參數個數。
 $*:傳遞給腳本或函數的所有參數。
 $@:傳遞給腳本或函數的所有參數。被雙引號(" ")包含時,與 $* 稍有不同,區別如下2:
 $?:上個命令的退出狀態,或函數的返回值。
 $$:當前Shell進程ID。對於Shell腳本,就是這些腳本所在的進程ID。
 示例腳本:
    #!/bin/bash
    echo "File Name: $0"
    echo "First Parameter : $1"
    echo "Second Parameter : $2"
    echo "Quoted Values: $@"
    echo "Quoted Values: $*"
    echo "Total Number of Parameters : $#"
 執行腳本$./test.sh Tom Bob
    File Name : ./test.sh
    First Parameter : Tom
    Second Parameter : Bob
    Quoted Values: Tom Bob
    Quoted Values: Tom Bob
    Total Number of Parameters : 2
2.$*和$@的區別:
$*和$@都表示傳遞給函數或腳本的所有參數,不被雙引號(" ")包含時,都以"$1" "$2" … "$n" 的形式輸出所有參數。
但當它們被雙引號(" ")包含時,"$*" 會將所有的參數作爲一個整體,以"$1 $2 … $n"的形式輸出所有參數;"$@" 會將各個參數分開,以"$1" "$2" … "$n" 的形式輸出所有參數。
eg:for var in "$*"【去掉雙引號,執行後輸出的是整體】
   do
   echo "$var"
   done
執行:sh test.sh a b c

3.$? 也可以表示函數的返回值

4.echo -e  其中-e表示對轉義字符替換,如果不使用 -e 選項,將會原樣輸出
  echo -E  其中-E禁止轉義,默認也是不轉義的;使用 -n 選項可以禁止插入換行符
轉義字符:含義
\\:反斜槓
\a:警報,響鈴
\b:退格(刪除鍵)
\f:換頁(FF),將當前位置移到下頁開頭
\n:換行
\r:回車
\t:水平製表符(tab鍵)
\v:垂直製表符

5.命令替換的語法:
`command`
注意是反引號,不是單引號,此鍵位於Esc鍵下方。

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

########shell運算符
1.算術運算符
 運算符    說明          舉例
  +             加法      `expr $a + $b` 結果爲30。(a=10 b=20)
  -              減法      `expr $a - $b` 結果爲 10。
  *              乘法     `expr $a \* $b` 結果爲  200。
  /               除法      `expr $b / $a` 結果爲 2。
  %            取餘      `expr $b % $a` 結果爲 0。
  =             賦值      a=$b 將把變量 b 的值賦給 a。
  ==           相等。   用於比較兩個數字,相同則返回 true。  [ $a == $b ]
  !=            不相等。 比較兩個數字,不相同則返回 true。  [ $a != $b ]

原生bash不支持簡單的數學運算,但是可以通過其他命令來實現,如awk和expr,expr最常用。
expr 是一款表達式計算工具,使用它能完成表達式的求值操作。
 腳本示例:
 val=`expr 2 + 2`
 echo "Total value : $val"
 執行結果:Total value : 4
 注意:
 等號與val無空格
 表達式和運算符之間要有空格,例如 2+2 是不對的,必須寫成 2 + 2,這與我們熟悉的大多數編程語言不一樣。
 完整的表達式要被 ` `包含,注意這個字符不是常用的單引號,此鍵位於Esc鍵下方。

2.關係運算符列表
 運算符                              說明                                                           舉例
 -eq     檢測兩個數是否相等,相等返回 true。                                [ $a -eq $b ]
 -ne     檢測兩個數是否相等,不相等返回 true。                            [ $a -ne $b ]
 -gt      檢測左邊的數是否大於右邊的,如果是,則返回 true。     [ $a -gt $b ]
 -lt       檢測左邊的數是否小於右邊的,如果是,則返回 true。      [ $a -lt $b ]
 -ge     檢測左邊的數是否大等於右邊的,如果是,則返回 true。  [ $a -ge $b ]
 -le     檢測左邊的數是否小於等於右邊的,如果是,則返回 true。[ $a -le $b ]

注意:關係運算符只支持數字,不支持字符串,除非字符串的值是數字。

3.布爾運算符列表
  運算符                              說明                                                           舉例

  !         非運算,表達式爲 true 則返回 false,否則返回 true。     [ ! false ]
 -o       或運算,有一個表達式爲 true 則返回 true。         [ $a -lt 20 -o $b -gt 100 ]
 -a       與運算,兩個表達式都爲 true 才返回 true。         [ $a -lt 20 -a $b -gt 100 ]

4.字符穿運算列表
  運算符                              說明                                       舉例

 =      檢測兩個字符串是否相等,相等返回 true。     [ $a = $b ]
 !=      檢測兩個字符串是否相等,不相等返回 true。     [ $a != $b ]
 -z      檢測字符串長度是否爲0,爲0返回 true。     [ -z $a ]
 -n      檢測字符串長度是否爲0,不爲0返回 true。     [ -n $a ]
 str      檢測字符串是否爲空,不爲空返回 true。     [ $a ]

5.文件測試運算符列表

 操作符          說明                                                                                      舉例
 -b file     檢測文件是否是塊設備文件,如果是,則返回 true。         [ -b $file ]
 -c file     檢測文件是否是字符設備文件,如果是,則返回 true。         [ -b $file ]
 -d file     檢測文件是否是目錄,如果是,則返回 true。             [ -d $file ]
 -f file     檢測文件是否是普通文件,如果是,則返回 true。         [ -f $file ]
 -g file     檢測文件是否設置了 SGID 位,如果是,則返回 true。         [ -g $file ]
 -k file     檢測文件是否設置了粘着位(Sticky Bit),如果是,則返回 true。     [ -k $file ]
 -p file     檢測文件是否是具名管道,如果是,則返回 true。         [ -p $file ]
 -u file     檢測文件是否設置了 SUID 位,如果是,則返回 true。         [ -u $file ]
 -r file     檢測文件是否可讀,如果是,則返回 true。             [ -r $file ]
 -w file     檢測文件是否可寫,如果是,則返回 true。             [ -w $file ]
 -x file     檢測文件是否可執行,如果是,則返回 true。             [ -x $file ]
 -s file     檢測文件是否爲空(文件大小是否大於0),不爲空返回 true。     [ -s $file ]
 -e file     檢測文件(包括目錄)是否存在,如果是,則返回 true。         [ -e $file ]

########shell註釋
如果在開發過程中,遇到大段的代碼需要臨時註釋起來,過一會兒又取消註釋,怎麼辦呢?每一行加個#符號太費力了,可以把這一段要註釋的代碼用一對花括號括起來,定義成一個函數,沒有地方調用這個函數,這塊代碼就不會執行,達到了和註釋一樣的效果。


########Shell字符串
1.單引號字符串的限制:
 單引號裏的任何字符都會原樣輸出,單引號字符串中的變量是無效的;
 單引號字串中不能出現單引號(對單引號使用轉義符後也不行)。

2.雙引號的優點:
    雙引號裏可以有變量
    雙引號裏可以出現轉義字符

#######Shell數組
1.在Shell中,用括號來表示數組,數組元素用“空格”符號分割開。定義數組的一般形式爲:
  array_name=(value1 ... valuen)

2.讀取數組
 1)讀取數組元素值的一般格式是:
 ${array_name[index]}
 
 使用@ 或 * 可以獲取數組中的所有元素,例如:
 ${array_name[*]}
 ${array_name[@]}

 2)獲取數組的長度
 獲取數組長度的方法與獲取字符串長度的方法相同,例如:
 # 取得數組元素的個數
  length=${#array_name[@]}
  length=${#array_name[*]}
 # 取得數組單個元素的長度
  length=${#array_name[n]}

########Shell echo命令
1.echo命令,用於在屏幕上打印出指定的字符串

 如果變量與其它字符相連的話,需要使用大括號({ }):
 mouth=8
 echo "${mouth}-1-2009"

2. 顯示結果重定向至文件
 echo "It is a test" > myfile

########Shell printf命令
1.printf 命令用於格式化輸出, 是echo命令的增強版,printf 不像 echo 那樣會自動換行,必須顯式添加換行符(\n)。

2.printf 命令的語法:
 printf  format-string  [arguments...]
 format-string爲格式控制字符串,arguments爲參數列表。如果沒有 arguments,那麼%s用NULL代替,%d用0代替
 這裏僅說明與C語言printf()函數的不同:
    printf 命令不用加括號
    format-string 可以沒有引號,但最好加上,單引號雙引號均可。
    參數多於格式控制符(%)時,format-string 可以重用,可以將所有參數都轉換。
    arguments 使用空格分隔,不用逗號。

######Shell if語句
1.Shell 有三種 if ... else 語句:
    if ... fi 語句;
    if ... else ... fi 語句;
    if ... elif ... else ... fi 語句。
2.if ... else 語句也經常與 test 命令結合使用,如下:
    if test $[2*3] -eq $[1+5]; then echo 'The two numbers are equal!'; fi;

########Shell case esac語句
1.case ... esac 與其他語言中的 switch...case 語句類似,是一種多分枝選擇結構。
 case 語句匹配一個值或一個模式,如果匹配成功,執行相匹配的命令。case語句格式如下:

 case 值 in
 模式1)
    command1
    command2
    command3
    ;;
 模式2)
    command1
    command2
    command3
    ;;
 *)
    command1
    command2
    command3
    ;;
 esac
注意:
 取值後面必須爲 in ,每一模式必須以右括號結束
 ;;符號與其他語言中的break類似,意思是跳到整個case語句的最後。

########Shell for循環
1.for循環一般格式爲:

 for 變量 in 列表
 do
    command1
    command2
    ...
    commandN
 done
示例腳本:顯示主目錄下以 .bash 開頭的文件
    #!/bin/bash
    for FILE in $HOME/.bash*
    do
    echo $FILE
    done
執行結果:
    /root/.bash_history
    /root/.bash_logout
    /root/.bash_profile
    /root/.bashrc

########Shell while循環
1.while循環用於不斷執行一系列命令,也用於從輸入文件中讀取數據;命令通常爲測試條件。其格式爲:
 while command
 do
   Statement(s) to be executed if command is true
 done
示例腳本:while循環可用於讀取鍵盤信息。輸入信息被設置爲變量FILM,按<Ctrl-D>結束循環。
    echo 'type <CTRL-D> to terminate'
    echo -n 'enter your most liked film: '
    while read FILM
    do
    echo " Great film is the $FILM"
    done

命令執行完畢,控制返回循環頂部,從頭開始直至測試條件爲假。

########Shell break和continue命令跳出循環
1.break命令允許跳出所有循環(終止執行後面的所有循環)。
  break n 表示跳出第n層循環
示例腳本:
while :
 do
  echo -n "The number is (1-3):"
  read num
  case $num in
   1|2|3)echo "Your number is $num"
   ;;
   *)echo "The number is not between 1 to 3,game over!"
   break
   ;;
  esac
 done

2.continue命令與break命令類似,只有一點差別,它不會跳出所有循環,僅僅跳出當前循環。
   continue 後面也可以跟一個數字,表示跳出第幾層循環。
示例腳本:echo "Game over!"永遠不會被執行
while :
 do
  echo -n "The number is (1-3):"
  read num
  case $num in
   1|2|3)echo "Your number is $num"
   ;;
   *)echo "The number is not between 1 to 3!"
   continue
   echo "Game over!"
   ;;
  esac
 done


########Shell 函數
1.Shell 函數的定義格式如下:
 function_name () {
    list of commands
    [ return value ]
 }
 函數返回值,可以顯式增加return語句;如果不加,會將最後一條命令運行結果作爲返回值。

2.刪除函數也可以使用 unset 命令,不過要加上 .f 選項,如下所示:
   $unset .f function_name
########Shell 函數參數
1.調用函數時可以向其傳遞參數。在函數體內部,通過 $n 的形式來獲取參數的值,例如,$1表示第一個參數,$2表示第二個參數...
注意,$10 不能獲取第十個參數,獲取第十個參數需要${10}。當n>=10時,需要使用${n}來獲取參數。

########Shell 輸入輸出重定向
1.linux命令默認從標準輸入設備(stdin)獲取輸入,將結果輸出到標準輸出設備(stdout)顯示。
 一般情況下,標準輸入設備就是鍵盤,標準輸出設備就是終端,即顯示器。

2.輸出重定向的語法爲:
  $ command > file
 
  使用 >> 追加到文件末尾
  echo test >> file
3.輸入重定向的語法爲:
  command < file

4.重定向命令列表
 命令             說明
 command > file     將輸出重定向到 file。
 command < file     將輸入重定向到 file。
 command >> file     將輸出以追加的方式重定向到 file。
 n > file         將文件描述符爲 n 的文件重定向到 file。
 n >> file         將文件描述符爲 n 的文件以追加的方式重定向到 file。
 n >& m         將輸出文件 m 和 n 合併。
 n <& m         將輸入文件 m 和 n 合併。
 << tag         將開始標記 tag 和結束標記 tag 之間的內容作爲輸入。

5.重定向深入講解
  一般情況下,每個 Linux 命令運行時都會打開三個文件:
   標準輸入文件(stdin):stdin的文件描述符爲0,Linux程序默認從stdin讀取數據。
   標準輸出文件(stdout):stdout的文件描述符爲1,Linux程序默認向stdout輸出數據。
   標準錯誤文件(stderr):stderr的文件描述符爲2,Linux程序會向stderr流中寫入錯誤信息
 1)如果希望stderr重定向到 file,可以這樣寫:
    $command 2 > file
 2)如果希望 stderr 追加到 file 文件末尾,可以這樣寫:
    $command 2 >> file
 3)如果希望將 stdout 和 stderr 合併後重定向到 file,可以這樣寫:
    $command > file 2>&1 或 $command >> file 2>&1
 4)如果希望對 stdin 和 stdout 都重定向,可以這樣寫:
    $command < file1 >file2
command 命令將 stdin 重定向到 file1,將 stdout 重定向到 file2。

6. /dev/null 文件
如果希望執行某個命令,但又不希望在屏幕上顯示輸出結果,那麼可以將輸出重定向到/dev/null
注意:/dev/null 是一個特殊的文件,寫入到它的內容都會被丟棄;如果嘗試從該文件讀取內容,那麼什麼也讀不到。但是 /dev/null 文件非常有用,將命令的輸出重定向到它,會起到”禁止輸出“的效果。

########Shell 文件包含
1.Shell 也可以包含外部腳本,將外部腳本的內容合併到當前腳本
      . filename 或 source filename
  兩種方式的效果相同,一般使用點號(.),但是注意點號(.)和文件名中間有一空格。

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