天天看點

Bash Shell腳本程式設計-變量知識

Shell:GUI  CLI

提供互動式接口:提高效率

指令行展開:~ ,{}

指令别名:alias

指令曆史:history

Globbing:*,?,[],[^]

指令補全:$PATH指定的目錄下

路徑補全:TAB鍵

管道:|

輸入輸出重定向:>    >> 

提供程式設計環境:

bash自動運作腳本機制

面向過程(以指令為中心組織資料)的程式設計模型

腳本程式設計

輸入指令解決問題

程式是語句和表達式組成的

運作時根據一定流程來執行:

順序執行

選擇執行

循環執行

程式是指令+資料的

面向對象(以資料為中心來組織指令)

架構組織程式中的各個指令

程式運作模型:

編譯運作:

源程式——>預處理——>編譯——>彙編——>連結——>運作

# file /bin/cat
/bin/cat: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped      

# ldd /bin/cat         連結到的庫

linux-vdso.so.1 =>  (0x00007fff5c3ff000)
libc.so.6 => /lib64/libc.so.6 (0x00000035d0e00000)
/lib64/ld-linux-x86-64.so.2 (0x00000035d0600000)      

解釋運作:

向核心提出運作要求時是解釋器運作成程序

源程式——>無需編譯——>解釋器——>核心根據檔案的格式來判定可執行(腳本的第一行要寫入shebang,如#!/bin/bash)——>讓bash程式來執行

變量:命名的記憶體空間

變量名:存放在記憶體中,由解釋器和記憶體自行維護

變量值:存放在記憶體中,由使用者來維護

資料類型:127:01111111    7bit存儲空間

127:1,2,7,是字串,要24位來存儲

ASCII碼:0-9,a-z,A-Z,punction

0-127 ,128種變化,要7位就能存儲

0000   0000 - 0111 1111

1.定義了資料存儲格式

2.定義了資料表示範圍

3.定義資料可以參與的運算類型

強類型程式設計語言:嚴格區分類型

弱類型程式設計語言:不嚴格區分類型

bash:把所有值都預設當作字元存儲

類型:

數值型:

精确數值型:整數

近似數值型:float(單精度浮點),double(雙精度浮點)

計算機裡面有專門的浮點單元來進行

浮點數的存儲格式?

字元型:

單個字元,字元串string

布爾型:

true,false

邏輯運算:

與: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

異或:

1 異或 1 =0

1 異或 0 =1

bash的變量類型:

本地變量:隻對目前shell程序有效,對目前之外的其他shell等shell都無效。

環境變量:對目前shell程序及其子shell程序有效,對其他shell無效。

局部變量:僅對目前shell程序中的某段代碼空間内有效,通常用于函數本地程式。

位置變量:$1  , $2   ,。。。

特殊變量:$?,$0 ,$$ ,$# ,$* , $@

$# 傳遞到腳本的參數個數

$* 傳遞到腳本的參數,與位置變量不同,此選項參數可超過9個

$$ 腳本運作時目前程序的ID号,常用作臨時變量的字尾,如 haison.$$

$! 背景運作的(&)最後一個程序的ID号

$@ 與$#相同,使用時加引号,并在引号中傳回參數個數

$- 上一個指令的最後一個參數

$? 最後指令的退出狀态,0表示沒有錯誤,其他任何值表明有錯誤

本地變量:隻是在使用者目前shell生存期的腳本中使用

無需事先聲明可直接使用

變量指派:# VAR_NAME=

變量引用:#echo "${VAR_NAME}"

[root@localhostretry]# a=1
[root@localhostretry]# echo "a=$a"
a=1
[root@localhostretry]# b='2'
[root@localhostretry]# echo "b=$b"
b=2
[root@localhostretry]# c="3"
[root@localhostretry]# echo "c=${c}"
c=3
[root@localhostretry]# a=1-$a
[root@localhostretry]# echo "a=$a"
a=1-1
[root@localhostretry]# b='2-$a'
[root@localhostretry]# echo "b=$b"
b=2-$a
[root@localhostretry]# c="3-$a"
[root@localhostretry]# echo "c=${c}"
c=3-1-1      
Bash Shell腳本程式設計-變量知識
#echo $username
 
#username=jerry
#echo $username
jerry
# echo '$username'         強引用,其中變量會被替換,所見所得
$username
# echo "$username"        弱引用,其中變量不會被替換
jerry
#set                                   顯示本地變量
#unset VAR_NAME        撤銷變量
#username=slackware
#useradd $username
#echo $username |passwd --stdin $username
Changingpassword for user slackware.
passwd:all authentication tokens updated successfully.      

注意習慣:

1.數字不加引号,其他預設加雙引号

2.把指令作為變量:反引号

CMD=`ls`

3.${WEEK}day  若變量和其他字元組成新的變量就必須給變量加上大括号。

4.養成将所有字元串變量用雙引号括起來的使用習慣,将會減少很多程式設計中遇到的錯誤。如 "$A" 或 "${A}"

特殊例子:awk調用shell變量引号例子

[root@localhostretry]# NUM=123
[root@localhostretry]# awk 'BEGIN {print '$NUM'}'
123
[root@localhostretry]# awk 'BEGIN {print "$NUM"}'
$NUM      

環境變量:

環境變量用于定義shell的運作環境,保證shell指令的正确執行,shell通過環境變量确定登入使用者名,指令路徑,終端類型,登入目錄等,所有的環境變量都是系統全局變量,可用于所有子程序。

無需事先聲明

$USER

$HOME

$UID

$SHELL

$PATH

變量指派:

 #export VAR_NAME=VALUE

 #declare -x  VAR_NAME=VALUE

變量引用:${VAR_NAME}

注意:bash内建了許多環境變量

顯示環境變量                  

#export

#printenv

#env

#export username        導出為環境變量

#unset VAR_NAME        撤銷變量臨時生效

變量隻讀:

readonly  VAR_NAME

declare -r VAR_NAME

退出目前shell程序可撤銷

變量命名規則:

1.不能使用程式中的關鍵字

2.隻能使用數字,字母或者下劃線,而且不能以數字開頭

3.見名知意:username,userName,_

自定義環境變量生成環境JAVA環境配置執行個體:tomcat,resin,csvn,hadoop

export JAVA_HOME=/application/jdk
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH:$HOME/bin
export RESIN_HOME=/application/resin      

常見放在: /etc/profile   或者 /etc/

位置變量:

#scirpt1.sharg1 arg2…

$0,$1…${10}

算術運算:

letVAR=expression

$[epression]

$((epression))

'expr arg1 arg2 arg3'

計算整數之和

        #vi test.sh    
        #!/bin/bash
        #author:test
        declare -i sum=0
        sum=$[$1+$2]
        echo "the sum of $1 and $2:$[$1+$2]
        echo "the minus of $1 and $2:$[$1-$2]      

參數變量的輪替:

shift [n]

        #vi test2.sh    
        #!/bin/bash
        #author:test
        #echo $1
        shift
        #echo $1
        shift
        #echo $1
        shift      

特殊變量:

$0:擷取目前執行的shell腳本的檔案名,包括路徑

        #cat 14.sh    
        dirname $0
        basename $0
        #sh /root/14.sh
        /root
        14.sh      

$n:擷取目前執行的shell腳本的第n個參數值,n=1..9,當n為0時表示腳本的檔案名,如果n大于9後,用大括号括起來${10}

        #seq 7 |sed 's#[0-9]#$&#g'    
        #cat 13.sh
        #!/bin/bash
        echo$1 $2 $3 $4 $5 $6 $7 $8 $9 $10
        #sh 13.sh 1 2 3
        12 3 10      

$#:擷取目前shell指令行參數的總個數

        #cat 13.sh    
        #!/bin/bash
        echo$1 $2 $3 $4 $5 $6 $7 $8 $9 $10
        echo$#
        #sh 13.sh 1 2 3 4 5
        12 3 4 5 10
        5
         
        #sh 13.sh "1 2 3 45"
        12 3 4 5 1 2 3 4 50
        1      

$@:這個程式的所有參數"$1" "$2"  "$3"  … ,這是将參數傳遞給其他程式的最佳方式,因為它會保留所有内嵌在每個參數裡面的任何空白。

$*:擷取目前shell的所有參數,将所有的指令行參數視為單個字元串,相當于"$!$2$3"…

        echo 'total $#'    
        echo -e '$@\n'
        echo -e '$*\n'      

程序狀态變量:

$$:擷取目前shell的程序号PID

        #!/bin/bash    
        echo$$ >/root/pid.log
        whiletrue ; do
                uptime &>/dev/null
                sleep 2
        done
        #sh 15.sh &
        [1]3158
        #cat pid.log
        3158      

$!:擷取上一個指令的PID

$?:擷取執行的上一個指令的狀态碼(0為成功,非0失敗)

例如:編譯安裝程式時,make後查詢成功與否

make

echo $?

打包時也可以使用

$?傳回值參考:

0:表示運作成功

2:權限拒絕

1-125:表示運作識别,腳本指令,系統指令錯誤或參數傳遞錯誤

126:找到指令,但無法執行

127:未找到要運作的指令

>128:指令被系統強制結束

$_ :在此之前執行的指令或腳本的最後一個參數

Bash Shell腳本程式設計-變量知識

    練習:寫一個腳本,能接受一個參數,此參數用于使用者名

    1.建立此使用者

    2.給使用者添加密碼,密碼同使用者名

    #!/bin/bash    
    #author:test
    useradd$1 
    echo$1 |passwd --stdin $1      

    練習:寫一個腳本,能接受一個參數,此參數為系統上某文本檔案路徑

    1.顯示此檔案的總行數

    2.統計此檔案中的空白行數

    #!/bin/bash    
    wc-l $1 |cut -d' ' -f1
    grep'^[[:space:]]$' $1 |wc -l      

$*和$@的差別:

$*:将所有指令行所有參數視為單個字元,等同于"$1$2$3"

$@:将指令行每個參數視為單獨的字元串,等同于"$!" "$2"  $3" ,這是将參數傳遞給其他程式的最佳方式,因為它會保留所有内嵌在每個參數裡的任何空白。

    [root@localhost ~]# set -- "how old " are you.      傳入3個參數    
    [root@localhost ~]# echo $#                         現在有三個參數
    3
    [root@localhost ~]# for i in $* ; do echo $i ; done循環列印參數,用$*,
    how
    old
    are
    you.
    [root@localhost ~]# for i in $@ ; do echo $i ; done沒有雙引号情況
    how
    old
    are
    you.
    [root@localhost ~]# for i; do echo $i ; done      去掉in變量清單,相當于in"$@"
    howold
    are
    you.
    [root@localhost ~]# for i in "$@" ; doecho $i ; done  在有雙引号的情況下,參數裡引号内容當作一個參數輸出,這才真正符合我們傳入的參數需求。
    howold
    are
    you.
    .      

擷取系統運作級别:

    # runlevel=$(set -- $(runlevel);eval "echo \$$#" )    
    # echo $runlevel
    3      

1. eval command-line

其中command-line是在終端上鍵入的一條普通指令行。然而當在它前面放上eval時,其結果是shell在執行指令行之前掃描它兩次。如:

pipe="|"

evalls $pipe wc -l

shell第1次掃描指令行時,它替換出pipe的值|,接着eval使它再次掃描指令行,這時shell把|作為管道符号了。

如果變量中包含任何需要shell直接在指令行中看到的字元(不是替換的結果),就可以使用eval。指令行結束符(;| &),I/o重定向符(< >)和引号就屬于對shell具有特殊意義的符号,必須直接出現在指令行中。

2. eval echo \$$# 取得最後一個參數

如:cat last

evalecho \$$#

./lastone two three four

four

第一遍掃描後,shell把反斜杠去掉了。當shell再次掃描該行時,它替換了$4的值,并執行echo指令

3.以下示意如何用eval指令建立指向變量的“指針”:

x=100

ptrx=x

eval echo \$$ptrx 指向ptrx,用這裡的方法可以了解b中的例子

100 列印100

eval $ptrx=50 将50存到ptrx指向的變量中。