Linux Bash Shell學習(十五):變數類型和整型運算

來源:互聯網
上載者:User

  本文也即《Learning the bash Shell》3rd Edition的第六章Command-Line Options and Typed varilables之讀書筆記之二,但我們將不限於此。

  在之前,我們涉及的變數基本上是字串,也有整數,例如便是參數個數的$#。我們可以使用declare來制定變數的屬性。

變數類型定義

declare –a

name

:表示數組array。

declare –f

name

:表示是function的名字。

declare –F

name

:同上,但只顯示function的名字。這個和上面的具體差異不太明白,但是這兩者都很少使用,先不理會它們。

declare –i

name

:表示整數

declare –r

name

:表示唯讀。不能使用unset。對於唯讀變數,也可以使用readonly

name

的方式,相當於declare –r name

。readonly可以帶三個選項:-f表示這是個function的名字,-p表示列印所有的readonly的名字,-a表示這是個唯讀數組。

declare –x

name

:同export,即不僅在當前的環境中起作用,也在外部的shell環境中起作用。

整型運算

  我們可以通過declare -i來定義整型變數。在上一次的學習中,使用了$(($OPTIND - 1))來進行計算$((…))是用於進行整型運算的。在$((…))中,我們並不需要對變數加上$來表示它的值,也不需要預先聲明這個變數是個整型。在雙引號下也能進行有效運算。下面是個例子:

#declare -i aa=13

aa=13

echo '$((aa-3))'=$((aa-3))

echo '$(($aa-3))'=$(($aa-3))

#date顯示日期,date +%j表示今天是年度的第幾天,$(command)表示其顯示結果

echo "Only $(( (365-$(date +%j)) / 7

)) weeks until the New Year"

  前面兩個echo得到的值都是10,我們也不需要預先聲明aa是個整數,因為$((…))已經表明是整型的運算,會自動將字元變為整數。

運算類型和C語言一樣。也支援$((x += 2))的格式,包括下面幾種操作。在下面的例子中我們引用了上面aa=13。

  • ++ :$((aa++))為13,並將aa賦值為14,注意使用$(($aa++))會報錯,無法解析13++的含義,所以為了簡潔並且不產生錯誤,不在運算式中加入$,如果是$((++aa))為14,並將aa賦值為14,這與C語言是一樣的。
  • -- :$((aa--))為13,並將aa賦值為12,如果是$((--aa))為12,並將aa賦值為12。
  • +
  • -
  • *
  • /
  • %:求餘:$((aa%5))=3
  • **:這個在C語言中是沒有的,表示Exponentiation,即取冪。例如上面例子中$(($aa**3))相當於13*13*13=2197
  • <<
  • >>
  • &
  • |
  • ~
  • !
  • ^

  還支援邏輯運算,包括<, >, <=, >=,==,!=,&&,||,

這些也與C語言一樣。例如$((3>1))為1。這和命令運行return 0表示真是不一樣的。一個是邏輯運算的結果,一個是exit status。例如上面$((3>1))為1,邏輯計算結果為1,而執行結果的 exit status為0。這兩個概念需要區分。

  我們在http://blog.csdn.net/flowingflying/archive/2009/12/22/5069646.aspx

中給出同[ … ]進行條件判斷的方式,這裡>,<,=等符號是用於判斷字串的,表示用於比較數位,在[ … ]中,如果對數字進行比較,需要使用-lt, –gt, –le, –ge, –eq, –ne

。使用[ … ],例如if [ 3 –gt 20 ]; then,條件不成立,但是[ 3 > 20 ],則成立,因為此刻比較的是字串。所以這是很容易引起混淆的。如果需要表達比較複雜,例如[ /( 3 -gt 2 /) || /( 4 -le 1 /) ]是不太好閱讀的。我們需要強調一點:在if [ condition ]; then中,shell對於function或者command是已0來表示成功,因此if也是判斷是否為0,這和$(())的數學邏輯運算是不一樣的。對於上面的例子,可以使用if [ $(((3 > 2) && (4 <= 1))) = 1 ]

,前面(((3 > 2) && (4 <= 1))) 運算結構為1,然後進行[ str1 = str2 ]的比較,判斷是否成立。這樣寫仍然很麻煩,以及使用if  (((3 > 2) && (4 <= 1)))

,即((…))

的方式表示。

對於數學運算的賦值,使用$((...))有時顯的比較繁複,可以使用let,格式如下:

let intvar

=expression

  let表示expression是個數學運算,無須使用$(())來作進一步表明,這樣的賦值方式簡潔很多。 等號前後是沒有空格的,在expression的運算式中也是沒有空格的,如果有空格必須用引號引起來,可以是單引號,也可以是雙引號,let x=1+4;let x='1 + 4';let x="1 + 4",這三個同樣都是給x賦值為5。下面是一個例子,擷取指定目錄的所佔大小空間:

function test1

{

    echo "test1 ${*}"

    for dir in ${*:-.}; do

        if [ -e $dir ]; then

            # du - estimate file space usage,返回block數目

            result=$(du -s $dir | cut -f 1)

            let total=$result*1024

            echo -n "Total for $dir = $total bytes"

            if [ $total -ge 1048576 ]; then

                echo " ($((total/1048576)) Mb

)"

            elif [ $total -ge 1024 ]; then

                echo " ($((total/1024)) Kb

)"

            fi

        fi

    done

}

  下面是一個較大的例子,使用這本書一直在用的pushd和popd的例子。進行了一些功能加強。當pushnd +n時,將第N個元素移到最上面,並進入該目錄,如果沒有參數,將最上的兩個元素交換,並進入交換後最top的目錄,否則安原pushd的處理方式進行處理。如果popnd +n,則將第N個元素從stack中刪除,其他的同popd的處理。

#擷取在stack中第N的參數,從0開始計算,並將前N的存放stackfront,後N的存放在stack中

function getNdirs

{

    echo getNdirs $@

    stackfront=''

    let count=0

    #通過數學計算和數字判度,可以向C那樣進行次數的控制,由於for是用於列表元素,所以使用while,迴圈之後,stackfront儲存前N個entry,含N,stack則存貯後面的元素。而target存貯第N個元素

    while [ $count -le $1 ] && [ -n "$stack" ]; do

        # target為stack中最top level的entry,含後面的空格

        target=${stack%${stack#* }}

        # 將最top的entry存放在stackfront的後面   

        stackfront="$stackfront$target"

        # stack為取出最top entry後的值

        stack=${stack#$target}

        let count=count+1

    done

    # 將第N個元素重複從stackfont中移出,則stackfont存貯N之前的元素

    stackfront=${stackfront%$target}

}

# 當pushnd +n時,將第N個元素移到最上面,並進入該目錄,如果沒有參數,將最上的兩個元素交換,並進入交換後最top的目錄,否則安pushd的處理方式進行處理。

function pushnd

{

    echo

    echo pushnd $@

    #檢查如果是pushnd +n的情況,需要將地N個元素移到最上方   

    if [ $(echo $1 | grep '^+[0-9][0-9]*$') ]; then

        # 將參數1,去除+,擷取n

        let num=${1#+}

        getNdirs $num

        stack="$target$stackfront$stack"

        cd $target

    elif [ -z "$1" ]; then

    # case of pushnd without args; swap top two directories

        firstdir=${stack%% *}

        stack=${stack#* }

        seconddir=${stack%% *}

        stack=${stack#* }

        stack="$seconddir $firstdir $stack"

        cd $seconddir

    else

    # normal case of pushd dirname

        dirname=$1

        # -a等同於 &&

        if [ /( -d $dirname /) -a /( -x $dirname /) ]; then

            stack="$dirname ${stack:-$PWD" "}"

            cd $dirname

        fi

    fi

    echo "stack=$stack"

    echo "directory=$PWD"

}

# 如果popnd +n,則將第N個元素從stack中刪除,其他的同popd的處理

function popnd

{

    echo

    echo popnd $@

    if [ $(echo $1 | grep '^+[0-9][0-9]*$') ]; then

    # case of popd +n: delete n-th directory from stack

        let num=${1#+}

        getNdirs $num

        stack="$stackfront$stack"

#      cd ${stack%% *}

     else

        if [ -n "$stack" ]; then

            stack=${stack#* }

            if [ -n "$stack" ]; then

                cd ${stack%% *}

            else

                echo "stack becomes empty."

            fi

        else

            echo "stack already empty."

        fi

    fi

    echo "stack=$stack"

    echo "directory=$PWD"

}

pushnd /home

pushnd /etc

pushnd /home/wei/mywork

pushnd +3

pushnd

pushnd +1

popnd +3

popnd

popnd

popnd

for的應用

  我們希望for和C或者JAVA那樣使用,這樣在數組的情況下非常方便,格式為:

for (( initialisation

; ending condition

; update

))

do

        statements

...

done


  如果使用for((;;))

澤則表示一個無限迴圈,在statements中可以用break來退出迴圈。下面是一個九九乘法表的例子:

for (( i=1; i <= 9 ; i++ ))

do

        for (( j=1 ; j <= 9 ; j++ ))

        do

                echo -ne "$(( j * i ))/t"

        done

        echo

done

相關連結: 我的Linux操作相關文章

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.