shell編程基礎

概述

Shell的概念是源自Unix的命令解釋器。Shell不只可解釋用戶輸入的命令,同時,可解釋執行基於命令的腳本語言。使用shell腳本能提升用戶操做和管理員進行系統管理的效率。shell腳本擅長處理純文本類型的數據,而Linux中幾乎全部的配置文件、日誌都是純文本類型。python

編寫腳本

腳本書寫規範

  1. 腳本統一存放目錄
  2. 選擇解釋器, 開頭要寫#! XXX,內核根據#!後的解釋器來肯定用哪一個解釋器解釋腳本內容
  3. 編輯腳本使用vim, 配置~/.vimrc方便我的書寫習慣
  4. 文件名規範,結尾以sh結束

shell的基本元素

  • #!/bin/bash 必須的,指出shell的類型
  • #註釋。在shell中,註釋寫在#以後,#以後的內容不會執行
  • 變量
  • 控制 循環分支

shell中的特殊符號

  1. #! 註明執行腳本採用的shell
  2. 變量符。
與反斜槓轉義符相反,使其後的普通字符做爲變量名,如a表示變量a的值。變量 字符長度超過1個時,用{}括起來
  3. 單引號。 被引發的字符所有作普通字符,即所有原樣echo 'my $SHELL'
  4. 雙引號 引號內的內容,除$、轉義符\、倒引號`這三個保留特殊功能,其餘字符均作普通字符。
  5. 倒引號(數字1鍵旁邊的那個鍵) 引號內的字符串當作shell命令行解釋執行(一樣的功能也可使用$()來使用),獲得的結果 取代整個倒引號括起來的部分。
  6. 反斜線 反斜線是轉義字符,它能把特殊字符變成普通字符。在某個字符前面利用反斜槓(\)可以阻止 shell把後面的字符解釋爲特殊字符。
  7. 表明0個或者多個特殊字符 例子 yum. 表明的可使yum.也能夠是yum.a、yum.ab、yum.abc 固然小數點後面能夠有多個字母
  8. ? 表明的是任意一個字符 例子 yum.? 能夠是yum.a yum.b yum.c,可是要注意小數點後面必須有任意一個字符
  9. [] 表明的是中括號中的任意一個
    • [abcdef] 能夠是a b c d e f 中的任意一個字母固然也能夠是數字
    • [-]表明的是一個範圍
    • [a-z] 表示的是字母a到z之間的全部字母[^]^是反向選擇符號從字面意思能夠知道也就是非的意思
    • [^abc]表示只要不a b c 這三個字符中的任意一個就選擇
  10. $( ) 能夠將命令替換輸出賦值給變量
  11. {} 經過括號擴展能夠生成須要的字串,括號中能夠包含連續的序列或使用逗號分隔的多個項目,連續的序列包括一個起點和一個終點
user@computer: ~$ echo {a,b,c}
 a b c
user@computer: ~$ echo user{1,5,8}
user1 user5 user8
user@computer: ~$ echo {0..10}
0 1 2 3 4 5 6 7 8 9 10
user@computer: ~$ mkdir {dir1,dir2,dir3}
user@computer: ~$ ls –ld dir{1,2,3}
複製代碼

變量

shell變量能夠保存路徑名、文件名或者一個數字等。分爲三類:shell

  • 本地變量: (局部變量)只在建立它們的Shell中使用,能夠在shell程序內任意使用和修改它 們。
  • 環境變量: 能夠在建立它們的Shell及其派生出來的任意子程序中使用。有些變量是用戶建立 的,其餘的則是專用的(好比PATH、HOME)。是系統環境的一部分,沒必要去定義它們,能夠在 shell程序中使用它們 。還能在shell中加以修改。
  • 內部變量: 由系統提供的。與環境變量不一樣,用戶不能修改它們。

本地變量

本地變量 在用戶如今的shell生命期的腳本中使用編程

使用本地變量的注意事項
  1. 等號兩邊不能夠有空格
  2. 取值包含空格,必須用雙引號括起來
  3. Shell變量能夠用大小寫字母,區分大小寫
  4. 變量是弱類型的, 不用聲明類型
變量聲明及賦值格式
變量=值(等號兩邊不能有空格)
複製代碼
變量的引用
$變量名   
 ${變量名}
 變量名爲1個字符時建議使用方式一,多餘一個字符時建議使用方式二
 舉例: $a ${abc}
複製代碼
清除變量
unset 變量名
user@computer: ~$ name=Jack
user@computer: ~$ echo ${name}
user@computer: ~$ unset name  # 注意,name前沒有$
複製代碼
設置只讀變量
設置變量時,不想再改變其值,能夠將之設爲只讀變量
 變量名=值
 readonly  變量名
複製代碼

環境變量

Bash預設了不少環境變量,實際使用中,能夠直接調用這些變量。環境變量能夠用於全部子程序,着包括編輯器、腳本和應用vim

內置環境變量
變量 意義
HOME 表明使用者的家目錄。cd ~ 去到使用者的家目錄 或者利用 cd 就能夠直接回到使用者家目錄了。
SHELL 目前這個環境使用的 SHELL 是哪一個程序? 若是是 bash 的話,預設是 /bin/bash
PWD 用戶當前工做目錄的路徑。它指出用戶目前在Linux文件系統中處在什麼位置。它是由Linux自動設置的
HISTSIZE 這個與「歷史命令」有關,曾經下達過的指令能夠被系統記錄下來,而記錄的「數目」則是由這個值來設定的。
PATH 就是執行文件搜尋的路徑,目錄與目錄中間以冒號(:)分隔,因爲文件的搜尋是依序由PATH的變量內的目錄來查詢,因此,目錄的順序也很重要。
環境變量注意事項
  • 環境變量能夠在命令行中設置,但用戶註銷時這些值將丟失
  • 環境變量均爲大寫
  • 必須用export命令導出
設置環境變量
variable-name=value
export variable-name(環境變量名大寫)
複製代碼
顯示環境變量
env 能夠看到全部的環境變量
echo $環境變量名 (顯示一個變量)
複製代碼
清除環境變量
unset 環境變量名
複製代碼
修改path環境變量
修改PATH環境變量,使腳本不用加路徑,直接輸入文件名字便可執行。
# 命令行修改環境變量
如下在用戶user主目錄下操做:
mkdir shdir && cd shdir
vi hello
chmod 755 hello
cdexport PATH=$PATH:$HOME/shdir
在任何目錄下,輸入hello便可執行該文件。
本方式下環境變量若是修改錯了,exit退出後從新登錄便可恢復系統默認的值。
複製代碼
配置文件中修改環境變量
注意,修改環境變量前最好先備份一下舊的:
export tem=$PATH
echo $tem >>pathbake

須要知道環境變量與哪些配置文件有關:不一樣發行版會有不一樣,但命名仍是有通性的:
find / -name 「*profile」
find / -name 「*bashrc」
全局配置文件/etc/profile
本地配置文件~/.bashrc
複製代碼

內部變量

內部變量是Linux所提供的一種特殊類型的變量,這類變量在程序中用來做出判斷。在shell程序內這類變量的值是不能修改的。數組

部份內部變量
變量 意義
$# 傳送給shell程序的位置參數的數量
$? 最後命令的完成碼或者在shell程序內部執行的shell程序(返回值)
$0 shell程序的名稱
$* 調用shell程序時所傳送的所有參數的單字符串,"參數1", "參數2"…形式保存的參數
$@ "參數1", "參數2"…形式保存的參數
$n 第n個參數
$$ 本程序的PID
$! 上一個命令的PID

輸入與輸出

輸入

# read 從鍵盤上讀取變量的值
read  [選項]  變量名列表
    經常使用選項
    -a ANAME   將輸入讀入ANAME的數組      
    -n NCHARS  讀入N個字符                
    -p PROMPT  顯示一個提示                       
    -r         取消轉移                           
    -s         安靜模式,輸入的字符將不會提示     
    -t TIMEOUT 超過指定時間,read自動中止 
複製代碼

輸出

echo  [選項]  字符串
    經常使用選項
    -n  不在最後自動換行               
    -e  啓用反斜線控制字符的轉換       
    -E  不處理轉義字符。此爲缺省選項; 
複製代碼
#! /bin/bash
# 輸入一句話,打印輸入的話
read -p 'please type some words, I will print them: ' words
echo $words
複製代碼

條件測試

test 條件表達式

# test
若是測試條件爲真,test命令會返回0,不然返回一個非0的數值
test 語句與if/thencase語句一塊兒,構成shell編程的控制轉移結構
複製代碼

[] 條件表達式

[ 條件表達式 ]	
方括號的內側兩邊各需一個空格
條件表達式的值爲真返回零,爲假時返回非零值
複製代碼

文件狀態判斷

條件語句 真假
-d filename 若文件filename爲目錄文件,則返回真
-f filename 文件是否存在且爲普通文件,則返回真
-r filename 若文件filename可讀,則返回真
-s filename 若文件filename的長度大於0,則返回真
-w filename 若文件filename可寫,則返回真
-x filename 若文件filename可執行,則返回真
-e filename 文件是否存在
#! /bin/bash
# 輸入文件的絕對路徑,判斷文件是否存在
read  -p 'input file path: ' file
if [ -e $file ]
    then
    echo '文件存在'
else
    echo '文件不存在'
fi
複製代碼

條件語句

if
if [ 條件表達式 ]; then
    命令序列
fi"條件表達式"的測試值爲真時,執行"命令序列",不然,執行條件語句後面的命令。條件表達
式與then之間的分號";"起命令分隔符的做用。
複製代碼
if-else
if  [ 條件表達式 ] 
    then
    命令序列1
else
    命令序列2
fi"條件表達式"的測試值爲真時,執行"命令序列1",不然,執行"命令序列2"。命令序列中的命令
能夠是一個或者多個。
複製代碼
if-elif-else
if test 條件表達式1
    then
    命令序列1
elif [ 條件表達式2 ]
    then
    命令序列2
else
    命令序列3
fi
這是包含二層嵌套的條件語句,當"條件表達式1"爲真時,執行"命令序列1",不然,在"條件表 達式2"爲真的狀況下,執行"命令序列2",不然,執行"命令序列3","命令序列3"屬於第2個條
件語句的一部分。
複製代碼
應用舉例
#! /bin/bash
# 判斷輸入的路徑是文件仍是目錄
read -p 'please input the file path: ' file
if [ -d $file ]
    then
    echo 'this is a directory'
elif [ -f $file ]
    then
    echo 'this is a file'
else
    echo 'wrong file type, or the file do not exist'
fi
複製代碼

數字操做符

操做符 含義
n1 –eq n2 判斷數字n1與n2是否相等,若相等,返回0,不然,返回1
n1 –ne n2 判斷數字n1與n2是否不等,若不等,返回0,不然,返回1
n1 –lt n2 判斷數字n1是否小於n2,如果,返回0,不然,返回1
n1 –gt n2 判斷數字n1是否大於n2,如果,返回0,不然,返回1
n1 –le n2 判斷數字n1是否小於或等於n2,如果,返回0,不然,返回1
n1 –ge n2 判斷數字n1是否大於或等於n2,如果,返回0,不然,返回1

字符串操做符

操做符 含義
string 若字符串string非空,則返回真
-n string 若字符串string長度大於0,則返回真
-z string 若字符串string長度爲0,則爲返回真
string1 = string2 若字符串string1和string2相等,則返回真
string1 != string2 若字符串string1和 string2不等,則返回真

邏輯操做符

操做符 含義
e1 –a e2 邏輯表達式e1和e2同時爲真時,返回0,不然,返回1
e1 –o e2 邏輯表達式e1和e2有一個爲真時,返回0,不然,返回1
! e1 若邏輯表達式e1不爲真時,返回0,,不然,返回1

循環語句

python風格for循環

for 變量名 in 參數列表
    do
    命令列表
done"參數列表"中的元素依次賦給"變量名",在每次賦值後執行"命令列表""參數列表"表示"變 量名"的取值範圍
複製代碼

c語言風格for循環

for ((初始化變量值;結束循環條件;運算))
    do
    命令序列
done
複製代碼

while

while [ 條件表達式 ] 
    do
    命令列表
done
循環執行"命令列表"中的命令,直至"條件表達式"的值爲假。
複製代碼

until

Until [ 條件 ]
    do
    命令序列
Done
直到條件知足時循環結束
複製代碼

應用舉例

#! /bin/bash
# 將指定目錄下(參數傳遞$1)的全部以.txt爲後綴的文件改名爲*.doc
directory=$1
if [ ! $directory ]
  then 
  echo "please input the argument directory"
  exit
fi
files=`ls ${directory}`
for file in $files;
  do
  if [ -f ${file} ]
    echo $file
    then 
    suffix=${file#*\.}
    echo $suffix
    if [[ $suffix == "txt" ]]
      then
      prefix=${file%\.*}
      mv $directory/$file $directory/$prefix.doc
    fi
  fi
done
複製代碼

函數

functionname() {
    命令列表
    return 
}
函數的調用方式爲:
functionname arguments
複製代碼
相關文章
相關標籤/搜索