shell腳本入門

一、基礎(chǔ)知識

編程語言有低級語言和高級語言兩類。
高級語言也有編譯型和解釋型的區(qū)分,編譯型語言有C,C++,jave;解釋型語言有shell,perl,python
shell腳本是一種包含聲明或命令,并符合一定格式的文本文件

shell作為一種過程式解釋型的編程語言,它的基本組織結(jié)構(gòu)有:

數(shù)據(jù)存儲:變量、數(shù)組
表達式
語句:if while case

shell腳本的格式有:

#!SHEBANG    
CONFIGURATION_VARIABLES     
FUNCTION_DEFINITIONS    
MAIN_CODE

shell腳本格式要求首行必須是shebang機制 ,shebang也是指明文件調(diào)用的解釋器類型

#!/bin/bash     
#!/usr/bin/python    
#!/usr/bin/perl      

運行腳本:

給予執(zhí)行權(quán)限,通過具體的文件路徑指明文件執(zhí)行。    
直接運行解釋器,將腳本作為解釋器程序的參數(shù)運行。

二、變量: 命名的存儲空間

數(shù)據(jù)的存儲方式:

字符:   
數(shù)值:整型,浮點型 

變量類型
作用:

1、定義數(shù)據(jù)存儲格式
2、定義參與的運算    
3、表示的數(shù)據(jù)范圍

類型:

字符    
數(shù)值:整型,浮點數(shù)

編程語言的變量又有強類型和弱類型的區(qū)分

強類型:jave,C++
    變量不經(jīng)過強制轉(zhuǎn)換,它永遠是這個數(shù)據(jù)類型,不允許隱式的類型轉(zhuǎn)換,故需要定義數(shù)據(jù)類型
弱類型:bash
   變量會有隱式轉(zhuǎn)換,故不需要指定數(shù)據(jù)類型,所有要存儲的數(shù)據(jù)都當做字符進行,不支持浮點數(shù)

三、邏輯運算

與: 
    1 && 1 = 1    
    1 && 0 = 0   
    0 && 1 = 0
    0 && 0 = 0
或: 
    1 || 1 = 1
    1 || 0 = 1
    0 || 1 = 1
    0 || 0 = 0
非:
    !1 = 0
    !0 = 1
異或:相同為假,不同為真 
短路運算:
    短路與:
        第一個為0,結(jié)果必為0   
        第二個為1,第二個必須要參與運算
    短路或:
        第一個為1,結(jié)果必為1
        第一個為0,第二個必須參與運算

四、bash中的變量的種類

根據(jù)變量的生效范圍為標準:

本地變量:生效范圍為當前shell進程,對當前shell之外的其他的shell進程無效,包括當前shell的子shell進程均無效;    
環(huán)境變量:生效范圍為當前shell進程及其子進程;    
局部變量:生效范圍為當前shell進程中某代碼片段(通常指函數(shù));  
位置變量:$1,$2,...來表示,用于讓腳本在腳本代碼中調(diào)用通過命令行傳遞給它的參數(shù);    
特殊變量:$?,$0,$*,$@,$#,$$    

本地變量:

變量賦值:name=“value”
    可以使用單引號:
        value:
            (1)可以是直接賦值:name=“filename”
            (2)變量引用:name=“$username”
            (3)命令引用:name=`COMMAND`,name=$(COMMAND)
變量引用:$(name),$name
    "":弱引用,其中的變量引用會被替換為變量值;
    '':強引用,其中的變量引用不會被替換為變量值,而保持原字符串;
顯示已定義的所有變量:
    set
撤銷變量:
    unset name

環(huán)境變量:

變量聲明、賦值
    export name=VALUE
    declare -x name=VALUE
變量引用:$name,$(name)
顯示所有環(huán)境變量:
    export
    env
    printenv
撤銷變量:
    unset name
bash中有很多內(nèi)置的環(huán)境變量,PATH,SHELL,UID,HISTSIZE,PWD,OLD,HISTFILE,PS1

變量命名法則:

1、不能使用程序中的保留字,如if、for
2、只能使用數(shù)字、字母及下劃線,且不能以數(shù)字開頭
3、最好見名知義

只讀變量:

設(shè)置只讀變量:
    readonly name
    declare -r name 
查看只讀變量:
    readonly -p 

位置變量:

在腳本代碼中調(diào)用通過命令行傳遞給腳本的參數(shù):
    $1,$2,....:對應調(diào)用第1,第2....個參數(shù)
         shift [n] 調(diào)換位置,n不能大于參數(shù)的個數(shù)
    $0:調(diào)用命名本身
    $*:傳遞給腳本的所有參數(shù),將所有參數(shù)作為一個整體字符傳遞
    $@:傳遞給腳本的所有參數(shù),每一個參數(shù)獨立傳遞,與$*只有在使用“”引起來時才有區(qū)別
    $#:傳遞給腳本的參數(shù)個數(shù)   

五、bash的配置文件

按生效范圍劃分:存在兩類
    全局配置:
        /etc/profile
            /etc/profile.d/*.sh
        /etc/bashrc    
    個人配置:
        ~/.bash_profile
        ~/.bashrc
按功能劃分:存在兩類
    profile類:為交互式登錄的shell提供配置
        全局:/etc/profile,/etc/profile.d/*.sh
        個人:~/.bash_profile
        功用:
            (1)用于定義環(huán)境變量
            (2)運行命令和腳本
   
    bashrc類:為非交互式登錄的shell提供配置
        全局:/etc/bashrc
        個人:~/.bashrc
        功用:
            (1)定義命令別名
            (2)定義本地變量
shell登錄:
    交互式登錄:
        直接通過終端輸入賬號密碼;
        使用“su -UserName”或“su -l UserName”切換的用戶
        讀取文件的順序:
            /etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
    非交互式登錄:
        su UserName
        圖形界面下打開終端
        執(zhí)行腳本
        文件讀取順序:
            ~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh 
編輯配置文件定義的新配置的生效方式:
    (1)重新啟動shell進程
    (2)使用source或.命令進程   

六、bash中進行算數(shù)運算

+,-,*,/,%,...
實現(xiàn)算數(shù)運算:
    (1)let var=算數(shù)表達式
        sum1=3;sum2=4;let sum=$sum1+sum2
    (2)var=$(算術(shù)表達式)
    (3)var=$((算術(shù)表達式))
    (4)var=$(expr arg1 arg2 arg3...)
        sum=$(expr $num1 \* $num2)
            *在某些場景下需要轉(zhuǎn)義
            
bash有內(nèi)置的隨機數(shù)生成器:$RANDOM
    echo $[$RANDOM%60]  對60取模,即生成0-59之間的某個數(shù)
    echo $[$RANDOM%60+1]   取1-60之間的某數(shù)
增強型賦值:
    +=,-=,*=,/=,%=
    count+=1  <==> count=count+1
自增,自減:
    let var+=1 <==> let var++
    let var-=1 <==> let var--

練習:
1、編寫腳本sumid.sh,計算/etc/passwd文件中的第10個用戶和第20個用戶的id之和
#! /bin/bash
user10="head -n $2 $1 | tail -n 1|cut -d: -f3"
user20="head -n $3 $1 | tail -n 1|cut -d: -f3"
let sum=$user10+$user20
echo "user id sum is $sum"


2、編寫腳本/sumspace.sh,傳遞兩個文件路徑作為參數(shù)給腳本,計算這兩個文件中所有空白行之和
#!/bin/bash
spaceline1=grep "^[[:space:]]*$" $1 | wc -l
spaceline2=grep "^[[:space:]]*$" $2 | wc -l
echo "The sum of space line:$[spaceline1+spaceline2]"

3、當執(zhí)行這個腳本時會自動創(chuàng)建模板腳本文件,若腳本后沒有跟參數(shù)則提示用戶輸入生成的腳本文件名,若參數(shù)大于1個,則提示參數(shù)錯誤并退出腳本
#!/bin/bash
[ $# -gt 1 ] &&{ echo "the args is error";exit;}
[ $# == 0 ] && read -s -p "please input script name: " name || name="$1"
echo "#!/bin/bash
# filename "$name"
# author:danran
# time is date +%F" >"$name"
chmod +x "$name"
vim "$name"
4、編寫腳本,統(tǒng)計/etc、/usr、/var目錄中有多少個一級子目錄和文件
#!/bin/bash
# danran
# time is Mon Jun 5 13:09:12 CST 2017
line1=ls $1 | wc -l
line2=ls $2 | wc -l
line3=ls $3 | wc -l
let sum=$line1+$line2+$line3
echo $sum

七、條件測試

判斷某需求是否滿足,需要由測試機制來完成;
Nnote:專用的測試表達式需要由測試命令輔助完成測試過程;
測試命令:
    test EXPRESSION
    [ EXPRESSION ]
    [[ EXPRESSION ]]
    Note:EXPRESSION前后必須有空白字符

bash的測試類型:
    數(shù)值測試
        -gt:大于
        -ge:大于等于
        -eq:等于
        -ne:不等于
        -lt:小于
        -le:小于等于
    字符串測試
        ==/=:等于
        >:大于
        <:小于
        !=:不等于
        ~=:左側(cè)字符是否能被右側(cè)的PATTERN所匹配
            Note:一般用于[[ ]]中
        -z “STRING” 測試字符串是否為空,空為真,不空為假
        -n “STRING” 測試字符串是否不空,不空為真,空為假
        eg  [ -z "$name" ]
            [[ $name ~= ^a ]]  匹配$name是否a開頭
        Note:用于字符串比較時的用到的操作數(shù)都應使用引號
    文件測試
        存在性測試:
            -a:FILE   同-e
            -e:FILE:文件存在性測試,存在為真
        存在性及類別測試:
            -b FILE:是否存在且為塊設(shè)備文件
            -c FILE:是否存在且為字符設(shè)備文件
            -d FILE:是否存在且為目錄文件
            -f FILE:是否存在且為普通文件
            -S FILE:存在且為套接字文件
            -L FILE 或 -h FILE:存在且為鏈接文件
            -p FILE:是否存在且為命名管道文件
        文件權(quán)限測試:(當前用戶)
            -r:文件是否存在且可讀
            -w:文件是否存在且可寫
            -x:文件是否存在且可執(zhí)行
        文件特殊權(quán)限測試:
            -g FILE:文件存在且擁有g(shù)uid權(quán)限,suid對腳本無效,腳本不是二進制文件
            -u FILE:文件存在且擁有suid權(quán)限
            -k FILE:是否存在且擁有sticky權(quán)限
        文件大小測試:
            -s FILE:文件是否存在且非空
        文件打開性測試:
            -t fd:fd表示文件描述符是否已經(jīng)打開且與某終端相關(guān)
            
            -N FILE:文件自從上一次打開讀取之后是否被修改過
            -O FILE:當前有效用戶是否為文件屬主
            -G FILE:當前有效用戶是否為文件屬組
        雙目測試:
            FILE1 -ef FILE2:FILE1與FILE2是否指向同一個設(shè)備上的相同inode,即硬鏈接
            FILE1 -nt FILE2:FILE1 是否新于FILE2
            FILE1 -ot FILE2:FILE1 是否舊于FILE2    
    組合條件測試:
        邏輯運算:
            第一種方式:
                COMMAND1 && COMMAND2    短路與
                COMMAND1 || COMMAND2    短路或
                ! COMMAND               非
            第二種方式:
                [ EXPRESSION1 -a EXPRESSION2 ]   與
                [ EXPRESSION1 -o EXPRESSION2 ]   或
                !EXPRESSION                     非
                必須使用測試命令進行
            [ -f /bin/cat -a -x /bin/cat ] && echo "true"
            [ ! -r /app/a -a ! -w /app/a ] && echo true <==> [ ! \( -r /app/a -o -w /app/a \) ] && echo "true"

練習:
1、編寫腳本/root/bin/excute.sh,判斷參數(shù)文件是否為sh后綴的普通文件,如果是,添加所有人可執(zhí)行權(quán)限否則提示用戶非腳本文件
#!/bin/bash
[ $# == 0 ] && read -p "please input fimename" name || name=$1
[ -f $name ] && [[ "$name" =~ .sh$ ]] && chmod a+x $name || echo "$name not scripts file"
2、編寫腳本/bin/per.sh,判斷當前用戶對指定的參數(shù)文件,是否不可讀并且不可寫
#!/bin/bash
[ ! -r $1 -a ! -w $1 ] && echo "$1 file not read and not write"
3、編寫腳本/root/bin/checkdisk.sh,檢查磁盤分區(qū)空間和inode使用率,如果超過80%,就發(fā)廣播警告空間將滿
#!/bin/bash
inode=df -i | grep "^/dev/sd*" | tr -s ' ' '%'| cut -d'%' -f5| sort -r | head -n 1
disk=df | grep "^/dev/sd*" | tr -s ' ' '%'| cut -d'%' -f5| sort -r | head -n 1
[ $inode -gt 80 ] && echo "danran"
[ $disk -gt 80 ] && echo "dan"

八、bash自定義退出狀態(tài)碼

exit [n]:自定義退出狀態(tài)碼為n
    Note:腳本中一旦遇到exit命令,腳本會立即終止,終止退出狀態(tài)取決于exit命令后面的數(shù)字n。
Note:如果未給腳本指定退出狀態(tài)碼,整個腳本的退出狀態(tài)碼取決于腳本中執(zhí)行最后一條命令的狀態(tài)碼。

練習:編寫腳本/root/bin/argsnum.sh,接受一個文件路徑作為參數(shù);
如果參數(shù)個數(shù)小于1,則提示用戶“至少應該給一個參數(shù)”,并立即退出;
如果參數(shù)個數(shù)不小于1,則顯示第一個參數(shù)所指向的文件中的空白行數(shù)
#!/bin/bash
[ $# -lt 1 ] && (echo "please input a arge" && exit ) || echo "grep "^$" $1 | wc -l"

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容