歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> SHELL編程 >> Shell編程入門總結(三)

Shell編程入門總結(三)

日期:2017/3/3 14:07:29   编辑:SHELL編程

本文的主要內容:1、數組

2、命令組合3、進程替換

4、陷阱機制5、常見錯誤與防錯

一、數組Bash 中的數組僅限制為單一維度。對數組的支持第一次出現在 bash 版本2中。

1.創建一個數組$ a[1]=foo

$ echo ${a[1]}

foo

其中第一個命令把數組 a 的元素1賦值為 “foo”,第二個命令顯示存儲在元素1中的值。在第二個命令中使用花括號是必需的, 以便防止 shell 試圖對數組元素名執行路徑名展開操作

也可以用 declare 命令創建一個數組:

$ declare -a a

使用 -a 選項,declare 命令的這個例子創建了數組 a

2.數組賦值有兩種方式可以給數組賦值。

單個值賦值使用以下語法:name[subscript]=value

多個值賦值使用下面的語法:name=(value1 value2 ...)

例如:

$ days=(Sun Mon Tue Wed Thu Fri Sat)

$ days=([0]=Sun [1]=Mon [2]=Tue [3]=Wed [4]=Thu [5]=Fri [6]=Sat)

3.輸出整個數組的內容下標 * 和 @ 可以被用來訪問數組中的每一個元素

例如:

$ animals=("a dog" "a cat" "a fish")

$ for i in ${animals[*]}; do echo $i; done

a

dog

a

cat

a

fish

$ for i in ${animals[@]}; do echo $i; done

a

dog

a

cat

a

fish

$ for i in "${animals[*]}"; do echo $i; done

a dog a cat a fish

$ for i in "${animals[@]}"; do echo $i; done

a dog

a cat

a fish

4.確定數組元素個數例如:

$ a[100]=foo

$ echo ${#a[@]} #數組元素個數

1

$ echo ${#a[100]} #第100元素的長度

3

盡管我們把字符串賦值給數組元素100,但bash僅僅報告數組中有一個元素,這不同於一些其它語言

5.找到數組使用的下標因為 bash 允許賦值的數組下標包含“間隔”,確定哪個元素真正存在可以使用以下形式的參數展開:

${!array[*]}

${!array[@]}

例如:

$ foo=([2]=a [4]=b [6]=c)

$ for i in "${foo[@]}"; do echo $i; done

a

b

c

$ for i in "${!foo[@]}"; do echo $i; done

2

4

6

6.在數組末尾添加元素使用 += 賦值運算符

例如:

$ foo=(a b c)

$ echo ${foo[@]}

a b c

$ foo+=(d e f)

$ echo ${foo[@]}

a b c d e f

7.數組排序Shell 沒有直接排序的方法,但可通過管道給sort實現

例如:

#!/bin/bash

# array-sort : Sort an array

a=(f e d c b a)

echo "Original array: ${a[@]}"

a_sorted=($(for i in "${a[@]}"; do echo $i; done | sort))

echo "Sorted array: ${a_sorted[@]}"

8.刪除數組刪除一個數組,使用 unset 命令:

$ foo=(a b c d e f)

$ unset foo

亦可用unset命令刪除單個的數組元素:

$ foo=(a b c d e f)

$ unset 'foo[2]'

注:數組下標開始於0,數組元素用引號引起來可防止 shell執行路徑名展開操作。

給一個數組賦空值不會清空數組內容:

$ foo=(a b c d e f)

$ foo=

$ echo ${foo[@]}

b c d e f

引用一個不帶下標的數組變量,則指的是數組元素0:

$ foo=(a b c d e f)

$ echo ${foo[@]}

a b c d e f

$ foo=A

$ echo ${foo[@]}

A b c d e f

9.關聯數組例如創建顏色數組

declare -A colors

colors["red"]="#ff0000"

colors["green"]="#00ff00"

colors["blue"]="#0000ff"

訪問關聯數組元素:

echo ${colors["blue"]}

二、命令組合用一個 group 命令,或者用一個子 shell可以把命令組合在一起

組命令:{ command1; command2; [command3; ...] }

注:花括號與命令之間必須有一個空格,並且最後一個命令必須用一個分號或者一個換行符終止

子 shell:(command1; command2; [command3;...])

例如:

ls -l > output.txt
echo "Listing of foo.txt" >> output.txt
cat foo.txt >> output.txt
可以用命令組合改為:

{ ls -l; echo "Listing of foo.txt"; cat foo.txt; } > output.txt

(ls -l; echo "Listing of foo.txt"; cat foo.txt) > output.txt
三、進程替換

1.當子 shell 退出時,環境副本會消失,所以在子 shell 環境(包括變量賦值)中的任何更改也會消失,例如:

echo "foo" | read

echo $REPLY

因為管道線中的命令總是在子 shell 中執行,所以該REPLY變量的內容總是為空

2.進程替換有兩種表達方式:

一種適用於產生標准輸出的進程:<(list)

另一種適用於接受標准輸入的進程:>(list)

其中list 是一串命令列表

3.解決上面的 read 命令問題,可用進程替換,例如:

read < <(echo "foo")

echo $REPLY

4.進程替換允許我們把一個子 shell 的輸出結果當作一個用於重定向的普通文件,檢驗如下:

$ echo <(echo "foo")

/dev/fd/63

使用 echo 命令,查看展開結果,我們看到子 shell 的輸出結果,由一個名為 /dev/fd/63 的文件提供

5.例子:

#!/bin/bash
# pro-sub : demo of process substitution
while read attr links owner group size date time 

filename; do
    cat <<- EOF
        Filename:     $filename
        Size:         $size
        Owner:        $owner
        Group:        $group
        Modified:     $date $time
        Links:        $links
        Attributes:   $attr
    EOF
done < <(ls -l | tail -n +2)
這個循環對目錄列表的每一個條目執行 read 命令。列表本身產生於該腳本的最後一行代碼。這一行代碼把從進程替換得到的輸出 重定向到這個循環的標准輸入。這個包含在管道線中的

tail 命令,是為了消除列表的第一行文本,這行文本是多余的。

四、陷阱(trap)機制1.trap語法如下

trap argument signal [signal...]

其中argument是一個字符串,它被讀取並作為一個命令,signal 是一個信號的說明,它會觸發執行所要解釋的命令

2.例子:

#!/bin/bash
# trap-demo : simple signal handling demo
trap "echo 'I am ignoring you.'" SIGINT SIGTERM
for i in {1..5}; do
    echo "Iteration $i of 5"
    sleep 5
done

此腳本定義一個陷阱,當腳本運行時每當接受到一個 SIGINT 或 SIGTERM 信號時,就會執行一個 echo 命令

五、常見錯誤與防錯1.語法錯誤

丟失引號:

......

if [ $number = 1 ]; then

echo "Number is equal to 1.

else

......

其中echo語句後面缺少一個引號

丟失或意外的標記:

......

if [ $number = 1 ] then

echo "Number is equal to 1."

else

......

其中if測試語句後面缺少一個分號

預料不到的展開

......

number=

if [ $number = 1 ]; then

......

其中當number展開後為[ = 1 ],若為測試語句的第一個參數添加雙引號[ "$number" = 1 ]可更正此問題,此時展開後為[ "" = 1 ]

2.防錯編程:驗證假設例如:

cd $dir_name
rm *
若dir_name所指的目錄不存在則會刪除當前工作目錄中的所有文件

對此可將命令改為:

[[ -d $dir_name ]] && cd $dir_name && rm *
通常,當某種情況(比如上述問題)發生的時候,最好是終止腳本執行,並對這種情況提示錯誤信息:

if [[ -d $dir_name ]]; then
    if cd $dir_name; then
        rm *
    else
        echo "cannot cd to '$dir_name'" >&2
        exit 1
    fi
else
    echo "no such directory: '$dir_name'" >&2
    exit 1
fi
3.其他防錯技巧

驗證輸入

如:[[ $REPLY =~ ^[0-3]$ ]]

測試命令

如:echo rm *

將 rm 命令及其展開的參數列表打印出來,而不是執行實際的rm命令語句

使用echo輸出變量內容

。。。

參考:《The Linux Command Line》

Copyright © Linux教程網 All Rights Reserved