Shell學習筆記

1.Shell腳本

1.1 格式

首行 #!/bin/bash 指定解釋器

1.2 注釋

'#'開頭的行,'#!'是例外
此外,# 是特殊字符,可以出現在一些參數代換結構和在數值常量表達式中,具有特殊含義,而不會開啟一個注釋。‘#’也不會開啟一個注釋。

1.3 函數

function funname(){…}

或者

funname()
{
    statements;
}

只需要使用函數名就可以調用某個函數:funname

參數可以傳遞給函數,使用方法就好像函數是個新腳本一樣:

funname arg1 arg2...; #傳遞參數

在函數中使用傳入的參數:$1 第一個參數;$@ 所有參數。

其中:"$@"被擴展成"$1""$2""$3";

"$*"被擴展成"$1c$2c$3",即一個字符串。c為IFS的第一個字符。

有時我們需要知道命令或者函數的執行狀態,用$?可以查看前一個命令的返回值,如果命令成功退出,那么退出狀態為0,否則非0。

1.4 正文部分

流程控制+命令

1.5 執行:修改權限

轉為可執行程序
chmod +x ./test.sh #使腳本具有執行權限
./test.sh #執行腳本

1.6 流程控制

條件語句
if :

if condition
then
    command1 
    command2
    ...
    commandN
fi
if `ps -ef | grep ssh`;  
then 
    echo hello; 
fi

if else-if else :

if condition1
then
    command1
elif condition2
    command2
else
    commandN
fi

循環語句
for :

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done
for var in item1 item2 ... itemN; do command1; command2… done;

while :

i=1;total=0;
while [ $i -le 10 ]
do
    let total+=i
    let i++
    echo $total,$i
done
i=1; total=0;
while((i<=10))
do
    ((total+=i, i++))
    echo $total,$i
done

case語句: case語句可以用戶處理自定義參數。

case $num in
1) echo "January";;                 #雙分號結束
2) echo "Feburary";;
5) echo "may"                       #每個case可以有多條命令       
   echo "sdfd"
   echo "sdf";;                     #但最后一條命令一定是雙分號結束
*) echo "not correct input";;       #*)是其他值、default的意思
esac

1.7 while read line

while read line; do something ; done

1.8 參數處理

a) "$*"將所有的參數解釋成一個字符串,而"$@"是一個參數數組。
b) Shell內建函數getopts “:a:bc” opt

主要變量:
$OPTIND :   存儲所處理的選項在參數列表中的位置
$OPTARG :   存儲相應選項所帶的參數

例子:

while getopts ":a:b:cef" opt
do
    case $opt in
        a)echo "the $OPTIND has arg:$OPTARG";;#$OPTIND=3
        b)echo "the b has arg:$OPTARG";;
        c | e | f)echo "the $opt has no arg";;
        \?)echo "the $opt is invalid param";;
    esac
done

c) shift n 將位置命令左移n個

1.9 條件判斷

條件判斷應該放進方括號里,且方括號兩邊都應該留有空格。 [ ]
a) 字符串判斷
字符串比較時,最好用雙中括號,因為有時候采用單中括號會產生錯誤,所以最好避開它們。[[ $str1 = $str2 ]]

=           當兩個串有相同內容、長度時為真
!=        當串str1和str2不等時為真
-n          當串的長度大于0時為真(串非空)
-z          當串的長度為0時為真(空串)

b) 數值判斷

-eq     兩數相等為真 
-ne     兩數不等為真 
-gt     int1大于int2為真 
-ge     int1大于等于int2為真 
-lt     int1小于int2為真 
-le     int1小于等于int2為真

c) 文件判斷

-e file         若文件存在,則為真 
-d file         若文件存在且是一個目錄,則為真
-b file         若文件存在且是一個塊特殊文件,則為真
-c file         若文件存在且是一個字符特殊文件,則為真
-f file         若文件存在且是一個規則文件,則為真
-g file         若文件存在且設置了SGID位的值,則為真
-h file         若文件存在且為一個符合鏈接,則為真
-k file         若文件存在且設置了"sticky"位的值
-p file         若文件存在且為一已命名管道,則為真
-r file         若文件存在且可讀,則為真
-s file         若文件存在且其大小大于零,則為真
-u file         若文件存在且設置了SUID位,則為真
-w file         若文件存在且可寫,則為真
-x file         若文件存在且可執行,則為真
-o file         若文件存在且被有效用戶ID所擁有,則為真

d) 邏輯判斷

!      非
-a     與        &&
-o     或        ||

if [ $v –ne 0 –a $v –lt 2 ] 等價 if [ $v –ne 0 ] && [ $v –lt 2 ]
if [ $v –ne 0 –o $v –lt 2 ] 等價 if [ $v –ne 0 ] || [ $v –lt 2 ]
條件判斷部分可能會變得很長,一個優化的小技巧是利用&&和||運算符。

if condition
then
    command1
else
    command2
fi
[ condition ] && command1 || command2

這樣就用一行代替了上面的5行而實現的功能完全相同。
如果命令有多個,可以用{}括起來,當做一個命令塊。
這樣可以使判斷語句變得非常簡潔。

1.10 &&、||

cmd1 && cmd2
表示,當cmd1執行成功后,就執行cmd2,否則不執行。
cmd1 || cmd2
表示,當cmd1執行失敗后,就執行cmd2,否則不執行。

2.變量

2.1 系統變量

$n 該變量與腳本被激活時所帶的參數相對應。n是正整數,與參數位置相對應($1,$2...)
$? 前一個命令執行后的退出狀
$# 提供腳本的參數號
$* 所有這些參數都被雙引號引住。若一個腳本接收兩個參數,$*等于$1$2
$0 正在被執行命令的名字。對于shell腳本而言,這是被激活命令的路徑
$@ 所有這些參數都分別被雙引號引住。若一個腳本接收到兩個參數,$@等價于$1$2
$$ 當前shell的進程號。對于shell腳本,這是其正在執行時的進程ID
$! 前一個后臺命令的進程號

2.2 普通變量

  1. 賦值:var=value

獲取字符串的長度。len=${#var}

  1. 數值運算:let
    let命令后面的變量不用帶$,如:
    nu=10;
    let nu+=10; #nu=20
    但這個命令不能進行浮點數的運算。
  2. 浮點數運算:bc
    echo "4 * 0.6" | bc
    bc是一個強大的計算器,還可以進項如下操作:
    設定小數精度,scale=2,eg:echo "scale=2;3 / 8" | bc
    #.37 這是bc的特性,小于0的數,是不顯示小數點前的0的。
    進制轉換。用ibase設定輸入數字的進制,obase設定輸出數字的進制。
no=10
echo "obase=2;ibase=10;$no" | bc   #1010

計算平方以及平方根。

echo "10^4" | bc        #1000   平方
echo "sqrt(100)" | bc   #10     平方根

2.3 IFS

全稱是Internal Field Separtor,內部分隔符。
Shell 的環境變量分為 set, env 兩種,其中 set 變量可以通過 export 工具導入到 env 變量中。其中,set 是顯示設置shell變量,僅在本 shell 中有效;env 是顯示設置用戶環境變量 ,僅在當前會話中有效。換句話說,set 變量里包含了 env 變量,但 set 變量不一定都是 env 變量。這兩種變量不同之處在于變量的作用域不同。顯然,env 變量的作用域要大些,它可以在 subshell 中使用。
而 IFS 是一種 set 變量,當 shell 處理"命令替換"和"參數替換"時,shell 根據 IFS 的值,默認是 space, tab, newline 來拆解讀入的變量,然后對特殊字符進行處理,最后重新組合賦值給該變量。

eg:
$ cat test.txt
1
2
3
$ out=$(cat test.txt)
$ echo $out
1 2 3           #shell將(cat test.txt)的結果拆解,并用默認的分隔符(空格)重新組合,賦值給out,因此echo $out的結果不包含換行。

如果要保留cat test.txt中的換行符,一般情況下要做兩步:
1是,設定IFS為換行:IFS='\n'
2是,將$(cat test.txt)用雙引號引起來,表示不用
若指定IFS為換行符。

2.4 UID

特殊的環境變量,如果UID=0,表示當前以root用戶運行腳本。否則不是root

3.自增

Linux Shell中寫循環時,常常要用到變量的自增,現在總結一下整型變量自增的方法。

1)  i=`expr $i + 1`;
2)  let i+=1;
3)  ((i++));    #雙括號結構
http://www.cnblogs.com/chengmo/archive/2010/10/19/1855577.html
4)  i=$[$i+1];
5)  i=$(( $i + 1 ))

4.雙括號結構(())

雙括號結構是對shell中算數及賦值運算的擴展。
語法:
((表達式1,表達式2…))
特點:

  1. 在雙括號結構中,所有表達式可以像c語言一樣,如:a++,b--等。
  2. 在雙括號結構中,所有變量可以不加入:“$”符號前綴。
  3. 雙括號可以進行邏輯運算,四則運算.eg. echo $((a>1?2:3));注意四則運算中仍然不支持浮點數運算
  4. 支持多個表達式運算,各個表達式之間用“,”分開. eg:((a+1,b++,c++))
  5. 雙括號結構 擴展了for,while,if條件測試運算

5.數組

  1. 取數組長度 – '#'
arr=(1 2 3 4 5)
len=${#arr[@]}
  1. 打印特定索引的數組元素
echo ${arr[2]}      #2
  1. 打印出數組中的所有值-'*'、'@'
echo ${arr[*]}
echo ${arr[@]}

6.關聯數組

在關聯數組中,可以用任意的文本作為數組索引。先聲明才能使用

  1. 聲明一個關聯數組。
declare –A ass_array
  1. 賦值:
a)  ass_array=([index1]=val1 [index2]=val2)
b)  ass_array[index1]=val1
ass_array[index2]=val2
  1. echo ${ass_array[index1]}
  2. 列出數組索引:
    echo ${!ass_array[@]}

7.臨時文件或目錄

在shell腳本中經常要保存臨時的數據,如果使用認為創建臨時文件用戶保存臨時數據,則有可能出現重名的情況,導致覆蓋原來的數據。
mktemp prefile.xxx 創建以prefile開頭的隨機文件文件,并返回文件名,指定前綴時必須包含至少3個xxx。
主要參數:
-d : 創建一個目錄,dirname=mktemp -d
-u : 僅生成隨機文件名,但不創建實際的文件或目錄,tmpfile=mktemp -u

原文鏈接:http://blog.keepmovingxin.com/2016/05/02/Learn-shell/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Shell Study Notes 指導思想: 10分鐘語法+實操 變量 變量賦值 Here文檔 輸入到一個命令的...
    PennLi閱讀 270評論 0 0
  • 1.特殊文件:/dev/null與/dev/tty /dev/null:bit bucket(位桶),傳送到此文件...
    喜歡蘿莉的逗逼青年閱讀 538評論 0 48
  • 1.awk 對付文字處理工作,做一些文本/數據處理,最基本功能是在文件或字符串中基于指定規則瀏覽和抽取信息. 1....
    喜歡蘿莉的逗逼青年閱讀 750評論 0 50
  • 很久沒寫過字句了, 然后就一直追憶…… 發現離家后的我 就像失了憶 仿佛不記得自己都做了什么 不是想不起 而是每一...
    汐蕪閱讀 76評論 0 0
  • 如果你我在夢中相遇 請千萬不要叫醒我 就讓我永遠的沉浸在這迷夢里 細聽你均勻的呼吸 感受你每一寸肌膚的細膩 在無盡...
    慕容錦瑟閱讀 515評論 2 2