[Note] Linux學習筆記7 shell編程基礎

Note 7 Linux Shell編程基礎

基本概念

shell腳本,一個shell程序,由可執行的shell命令組成,以普通linux文件形式保存
運行一個shell腳本的方法:linux

  1. chomd u+x scriptfile ./scriptfileshell

  2. /bin/bash scriptfile編程

shell變量,shell容許使用一些讀寫存儲區,爲用戶和程序設計人員提供一個暫存數據的區域,分爲環境變量和用戶定義變量數組

環境變量用來定製shell運行環境,保證shell命令正確執行,全部環境變量會傳遞該shell的子進程
環境變量大多在/etc/profile文件中初始化,而profile是在用戶登陸時執行的。
用戶能夠在用戶的~/.profile中給部分或所有環境變量賦值,或者在~/.bashrc,~/bash_log,~/.bash_profile中修改,它們在bash啓動時執行
咱們能夠經過echo $變量名 來打印變量,具體的環境變量請自行查閱(set、env、declare、typeset、printecv等命令能夠顯示環境變量和其值)bash

用戶變量在shell腳本彙總被用於臨時的存儲空間,一個沒有初始化的變量自動被初始化爲一個空串,用shell內嵌命令declare、local、set、typeset來初始化用戶變量dom

程序流程控制命令,提供了對shell腳本中命令進行非順序執行或循環執行的功能ide

變量相關

bash並不要求你必定聲明變量,可是咱們能夠經過declare和typeset命令來聲明變量,對變量初始化,並設定它們的屬性,語法:函數

declare [options] [name[=value]]
typeset [options] [name[=value]]

經常使用options:oop

  • -a 每一個name是一個數組網站

  • -f 每一個name是一個函數

  • -i name是一個整數

  • -r 給每一個name標記上只讀屬性

  • -x 表示每一個name均可以被子進程訪問到
    例如:

declare -i age=20
declare -rx os=linux

注意:一個整型變量不能賦予非整型的值,非整型的變量能夠被賦予任何值

變量讀寫
語法:varable=value $varable
例子:

myloc=/usr/test
echo $myloc
ls $myloc

注意:(1)等號先後沒有空格 (2)讀取變量時前面加‘’$‘’

變量讀取--命令替代操做符
如下varable表明變量名,string表明一個字符串

  • $varable 返回變量的值,若是沒有初始化則返回null

  • ${varable} 返回變量的值,若是沒有初始化則返回null,經常使用於數組變量

  • ${varable:-string} 若變量存在且非空,返回變量的值,不然返回string的內容

  • ${varable:=string} 若變量存在且非空,返回變量的值,不然把string賦給變量並返回

  • ${varable:?string} 若變量存在且非空,返回變量的值,不然顯示字符串‘'varable:'和string

  • ${varable:+string} 若變量存在且非空,返回string的值,不然返回null

例程:

$echo $name     #name is null
                #this is space           
$name=xiaoming  
$echo $name     
xiaoming

$echo ${name:-john} ${place:=varIsNull}
xiaoming varIsNull
$echo ${place:?"not defined."}
bash: place: not defined.
$echo ${name:+defined}
defined
$echo ${place:+"not defined"}
$echo ${place:="hz"}
hz

符號"" '' *的使用
使用雙引號將值括起來,則容許使用$符號對變量進行替換,但對大多數的元字符(包括*)都將按字面意思處理
使用單引號將值括起來,則不容許使用變量替換,並不對它進行shell解釋
使用反斜槓去除字符的特殊含義,並把它們按字面意思處理,好比$

命令替換
當一個字符串被包含在一堆括號裏,並在前面加$符號,或者被包含在反引號 ` 中,則該字符串被做爲命令執行,並用命令的執行結果替換這個字符串自己。
語法:$(command) `command`

定義全局變量

declare -x[name-list]
typedef -x[name-list]
export [name-list]

以上命令把name-list中的變量名字和它們的值擴展到以後每個命令裏
例如:

$declare -x name=global

重設變量
unset [name-list]
將name-list中的變量重設爲null
例如:

unset name place

注意:不能重設只讀變量的值

shell腳本

讀入參數

1.從標準輸入設備讀入變量
read [options] var-list
用途:從標準輸入設備讀入一行,將讀入的詞存入var-list變量中,讀入的一行輸入由多個詞組成,中間由空格或tab分隔。若是這些詞的數量比列出的變量多,那麼將餘下的全部詞賦值給最後一個變量,反之,設爲null

2.直接傳遞給shell腳本
在運行腳本時,在腳本名以後直接輸入參數
例如:$bash scriptfile val1 val2 val3
這些變量的前9個存放在shell變量$1 到 $9中,可使用shift [N]命令把參數化向左移動N個位置
$#變量包含了傳遞的參數的個數
$* 和 $@ 都包含了全部參數的值,他們的區別在於,當被引號包括時,$@把每一個參數的值做爲一個字符串,而不是把全部參數的值做爲一個字符串
$0包含了腳本文件的名字

3.set命令
可使用set命令將值存到位置參數裏
例如:

$set $(date)
$echo "$@"
Thu July 20 21:33:09 PST 2016

date命令的輸出有6個域,被存到$1到$6之中

程序流程控制語句

推薦一個寫的不錯的網站
http://www.freeos.com/guides/lsst/
推薦一本書《linux命令行與腳本編程大全》,pdf下載地址
http://pan.baidu.com/s/1slkXFxN

一些shell編程練習及答案:

1.統計指定目錄下的普通文件、子目錄及可執行文件的數目,以及普通文件字節數總和,目錄的路徑名字由參數傳入

printf "Please input file path\n";
read filepath
i=0;
j=0;
fn=0;
dn=0;
xn=0;
bn=0;
#store filename in an array
for s in `ls $filepath`; do
    files[i]=$s;
    let "i++";
done
#traversal all files
while ([ $j -lt $i ]); do
    ts=$filepath"/"${files[j]};
    #if the file is ordinary file,fn++
    if [ -f $ts ]; then
        let "fn++";
        for ts in `wc -c $ts`; do
            res=$ts;
            break;
        done
        bn=$[$bn + $res];
    #if the file is directory,dn++
    elif [ -d $ts ]; then
        let "dn++";
    fi
    #if the file is executable,xn++
    if [ -x $ts ]; then
        let "xn++";
    fi
    let "j++";
done  
printf "%-10s : %-5d\n" Ordinary File $fn;
printf "%-10s : %-5d\n" Directory $dn;
printf "%-10s : %-5d\n" Executable File $xn;
printf "%-10s : %-5d\n" Total Byte $bn;

2.整數排序及尋找最大最小值

#prodecue random number
random(){
   min=$1;
   max=$2;
   ran=$[ $max - $min ];
   num=`date +%s+%N`;
   return $[ $num % $ran + $min ]; 
}
#store 100 random number into array
for((i=0;i<100;++i)); do
    random 1 10000;
    array[$i]=$?;
    printf "%d " ${array[$i]};
done
printf "\n";

#echo "Please input some integer";
#read -a array;
i=0;
mmin=201607010;
mmax=0;
while([ $i -lt ${#array[@]} ]); do
    if [ $mmin -gt ${array[$i]} ]; then
        mmin=${array[$i]};
    fi
    if [ $mmax -lt ${array[$i]} ]; then
        mmax=${array[$i]};        
    fi
    let "i++";
done
#inset sort algorithm using two for loop
#time complexity is O(n2)
num=${#array[@]};
for((i=1;i<num;++i));do
    tem=${array[$i]};
    for((j=i-1;j>=0;--j));do
        if [  ${array[$j]} -gt $tem ]; then
            array[$[ $j + 1 ]]=${array[$j]};
            array[$j]=$tem;
        fi
    done
done
#output the res:MAX,MIN,SORT
echo "Max: $mmax";
echo "Min: $mmin";
k=0;
echo "Sort:"
while [[ $k -lt $num ]]; do
    printf "%d " ${array[$k]};
    let "k++";
done
printf "\n";

3.輸入一個字符串,過濾掉全部非字母字符,而後判斷是否是迴文字符串

echo PLease input a string:
read str;
#filter other char 
str2=`echo -n $str|tr -d -c 'a-zA-Z'`;    
echo After filter:$str2;
len=`echo -n $str2|wc -c`;                
mid=`expr $len / 2`;                   
l=1;
#judge palindrome
while [ $l -le $mid ]; do
    c1=`echo -n $str2|cut -c $l`;
    c2=`echo -n $str2|cut -c $len`;
    if [ $c1 != $c2 ]; then
        echo "$str2 isn't a palindrome";
        break;
    fi
    l=$(($l+1));
    len=$(($len-1));
done
if [ $c1 = $c2 ];then
    echo "$str2 is a palindrome"
fi
相關文章
相關標籤/搜索