005.shell基礎(chǔ)

shell腳本基礎(chǔ)

shell腳本可以輸入多個(gè)命令并處理每個(gè)命令的結(jié)果。

創(chuàng)建shell腳本時(shí),需要在文件的第一行指定使用的解析器(#!/bin/bash)

通常shell腳本在行里,#號(hào)用作注釋行,不被執(zhí)行,第一行是個(gè)特例,它指定執(zhí)行的解析器

vim 第一個(gè)腳本文件.sh
#!/bin/bash
# 這是一個(gè)demo
date
wc file1
# 執(zhí)行腳本
sh ***.sh
./***.sh

特殊符號(hào)

  1. 反引號(hào)

    反引號(hào)(``):允許你把shell變量的結(jié)果輸出賦值給變量

    test=`date`
    echo $test #顯示的是時(shí)間
    test=`echo "hello world"`
    echo $test
    
  2. 重定向

    重定向符號(hào)指向數(shù)據(jù)流動(dòng)的方向。

    重定向(>,>>):允許你將某個(gè)命令的輸入輸出重定向到另一個(gè)位置

    date > file # 覆蓋原有數(shù)據(jù)
    date >> file # 追加數(shù)據(jù)
    

    輸入重定向(<):將文件內(nèi)容重定向到命令中

    > wc < file
    > wc <<aa
    > ok
    > world
    > aa
    

    ?

  3. 管道

    取代輸出重定向到文件件,可以將重定向到另一個(gè)命令,稱為管道連接。

    管道連接不是一個(gè)一個(gè)運(yùn)行的,在系統(tǒng)內(nèi)部將他們連接起來,一個(gè)命令輸出的同時(shí),另一個(gè)命令同時(shí)運(yùn)行,傳輸數(shù)據(jù)不會(huì)用的任何中間數(shù)據(jù)和中間文件

    ls > file
    sort < file
    ls | sort
    

數(shù)學(xué)運(yùn)算相關(guān)命令

expr:用來處理數(shù)學(xué)表達(dá)式,它可以識(shí)別一些不同的數(shù)字和字符串操作(操作符兩側(cè)的空格及轉(zhuǎn)移)


image.png

image.png
expr 1 + 5

expr 1 \* 5

vim test.sh
#!/bin/bash  #指定解析器
var1=3
var2=2
var3=`expr $var1 \* $var2`
echo $var3

sh test.sh
chmod 777 test.sh
./test.sh

echo $PATH
vim ~/.vimrc
set number #設(shè)置行號(hào)

#數(shù)學(xué)表達(dá)式簡單方法 $[operation]
var2=$[5+2]
echo $var2

shell腳本(條件語句)

if語句運(yùn)行if定義命令(如果退出狀態(tài)嗎為0,運(yùn)行then部分命令)

vim test.sh
if date 
then
     #語句塊
     echo "running then"
     echo "---------------"
fi
sh test.sh

#多命令用;分割
echo $var1;echo $var2

date
echo $?  #上一個(gè)狀態(tài)退出碼

if ssss
then
    #語句塊
    echo "running then"
    echo "---------------"
else
    #語句塊
    echo 'runing else'
fi

if ssss
then
    #語句塊
    echo "running then"
    echo "---------------"
elif date
then
    echo "else"
else
    #語句塊
    echo 'runing else'
fi

test命令(數(shù)值比較,字符串比較,文件比較)

格式1:test condition
格式2:[ condition ] (左右空格一般都要個(gè)加一個(gè)空格,否則會(huì)報(bào)錯(cuò))


image.png
#!/bin/bash
########################################## #####   **********
#####   **********
#########################################
if test 6 -gt 5
then
    echo "6 > 5"
fi            

if [ 6 -gt 5 ]
then
    echo "6 > 5"
fi   
#不能處理小數(shù)
image.png
  1. test的比較會(huì)將所有的標(biāo)點(diǎn)和大寫也考慮在內(nèi)。
  2. 要轉(zhuǎn)義大于小于號(hào),否則會(huì)被當(dāng)為重定向符號(hào)
  3. test命令字符串比較會(huì)使用標(biāo)準(zhǔn)的ASCII順序,根據(jù)每個(gè)字符的ASCII數(shù)值來決定排序順序。
  4. test命令使用標(biāo)準(zhǔn)的數(shù)學(xué)比較符號(hào)來表示字符串的比較,而用文本代碼表示數(shù)值比較。
 12 if [ aa = aa ]
 13 then
 14     echo "equal"
 15 fi
 16 
 17 user=aaaa
 18 testuser=aaaa
 19 if [ $user != $testuser ]
 20 then
 21     echo "no eque"
 22 else
 23     echo "eque"
 24 fi

if [ aaa \> bbb ]
then
     echo "aaaa>bbbb"
fi

var1=""
if [ -z var1 ]
then 
   echo "是空"
fi
image.png
 27 if [ -d $HOME ]
 28 then
 29     ls $HOME
 30     if [ -r $HOME ]
 31     then
 32         echo "$HOME is read"
 33     fi
 34 else
 35     echo "is not directory"
 36 fi

復(fù)合條件

if date && [ -n aaa ]
then
    echo "run"
else
    echo "no run"
fi

if-then語句高級(jí)特性

  1. 用于數(shù)學(xué)表達(dá)式的雙括號(hào)(空格可以省略,不需要轉(zhuǎn)義大于小于等符號(hào))
    (( ))雙括號(hào)命令允許你將高級(jí)數(shù)學(xué)表達(dá)式放入比較中,test命令只允許在比較中進(jìn)行簡單的算術(shù)操作

  2. 用于高級(jí)字符串處理功能的雙方括號(hào)(兩側(cè)空格必須存在)
    [[ ]] 雙方括號(hào)支持test命令的特性,并新增了另一個(gè)特性模式(正則表達(dá)式)匹配.


    image.png
if ((10 ** 2 >90));then
  ((v2= 10 ** 2))
  echo "v2="$v2
fi
 
if [[ $USER = w* ]];then
 echo "yes"
fi

case命令

  • 為了避免在一組可能的值中尋找特定值而寫出很長的if-then-else語句,引入case命令
  • case命令會(huì)檢查單個(gè)變量列表格式的多個(gè)值.
  • 通過豎線操作符來分割模式
  • 星號(hào)*會(huì)捕獲所有跟列出的模式都不匹配的值
  • 每一個(gè)語句塊一雙分號(hào)結(jié)尾
case $USER in
work333 | work1)
echo "welcome work work1";;
work2)
echo "welcome work2";;
*)
echo "welcome other";;
esac

shell腳本(循環(huán)語句for,while,until)

特殊的環(huán)境變量IFS, 稱為內(nèi)部字段分隔符(interal field separator) ,IFS環(huán)境變量定義了bash shell用作字段分隔符的一系列字符。>set |grep IFS 默認(rèn)情況下,bash shell會(huì)將空格、制表符、換行符定義為字段分隔符。

for test in Alabama Alaska Arizona California
do
   echo "The next is $test"
done

echo $test   #該值會(huì)在shell腳本的剩余部分一直保持有效

val="Alabama Alaska Arizona California"
for test in $val   # 從變量讀取迭代列表
do       
 echo "The next is $test"
done

# 注意單引號(hào)的轉(zhuǎn)義,及元素中帶空格的處理
for test in I\'am a boy, "you are a gril"  
do
  echo "The next is $test"
done

#從文件讀取迭代列表
for test in `cat bb`;
do    
   echo "The next is $test"
done

for ((i=0;i<10;i++))       #C語言風(fēng)格的for循環(huán)
do
  echo "The next number is $i"
done

for ((a=1,b=10;a<=10,b>2;a++,b--))   #C語言風(fēng)格的多個(gè)條件
do
  echo "$a -  $b"
done

while命令:
允許你在while語句行定義多個(gè)測試命令,只有最后一個(gè)測試命令的退出狀態(tài)碼會(huì)被用來決定什么時(shí)候結(jié)束循環(huán)。

val1=10
while [ $val1 -gt 0 ]
do
  echo $val1
  (( val1-- ))
  #val1=$[$val1-1]
done
 
val1=10
while echo $val1  #定義多個(gè)測試命令,只有最后一個(gè)測試命令的退出狀態(tài)碼會(huì)被用來決定結(jié)束循環(huán)
[ $val1 -gt 0 ]
do
  echo "This is flag"
  val1=$[$val1-1]
done

until命令:要求你指定一個(gè)通常輸出非零退出狀態(tài)碼的測試命令,一旦測試命令返回退出狀態(tài)碼0,則循環(huán)就結(jié)束了。

val1=10
until [ $val1 -eq 0 ]   #until也是支持同時(shí)指定多個(gè)命令的
do
  echo $val1
  ((val1--))
done

嵌套循環(huán):

for (( a=1;a<=3;a++ )) #嵌套循環(huán)
do
  echo "start loop $a"
  for ((b=1;b<=3;b++))
  do
    echo "Inside loop: $b"
  done
done

break和continue命令

for var1 in 1 2 3 4 5 6 7
do
  if [ $var1 -eq 5 ]
  then
    break         #跳出循環(huán)
  fi
  echo "echo $var1"
done
var1=10
 
while [ $var1 -gt 0 ]
do
  if [ $var1 -eq 5 ]
  then
      break
  fi
  echo "while echo $var1"
  ((var1--))
done


for ((a=1;a<4;a++))
do
  echo "Outer loop :$a"
  for ((b=1;b<100;b++))
  do
     if [ $b -eq 5 ];then
        break         #跳出最靠近的循環(huán)
     fi
     echo "         Inner loop: $b"
  done
done
echo "----------"
#跳出外部循環(huán)
for ((a=1;a<4;a++))
do
  echo "Outer loop :$a"
  for ((b=1;b<100;b++))
  do
     if [ $b -eq 5 ];then
        break 2        #n指明break要跳出的層級(jí),若不指明n則 默認(rèn)層級(jí)為1
     fi
     echo "         Inner loop: $b"
  done
done



for ((var1=1;var1<15;var1++))
do
   if [ $var1 -gt 5 ] && [ $var1 -lt 10 ]
   then
       continue          #continue設(shè)置提早結(jié)束執(zhí)行循環(huán)內(nèi)部的命令,但并不終止循環(huán)
   fi
   echo "Iteration number: $var1"
done
 
for ((a=1;a<=5;a++))
do
  echo "Iteration $a"
  for ((b=1;b<3;b++))
  do
    echo " b= $b"
    if [ $a -gt 2 ] && [ $a -lt 4 ]
    then
        continue 2  #指定要繼續(xù)的循環(huán)層級(jí)n
    fi
    var3=$[ $a*$b ]
    echo "   The result of $a * $b is $var3"
  done
done


shell腳本高級(jí)部分(函數(shù)定義,函數(shù)參數(shù),函數(shù)變量)

函數(shù)是可以起個(gè)名字并在代碼中任何位置重用的代碼塊。你要在腳本中使用該代碼塊時(shí),只要使用分配的函數(shù)名就行了

  1. 函數(shù)定義要在使用函數(shù)前
  2. 如果你重定義了函數(shù),新定義會(huì)覆蓋原來函數(shù)的定義,而不會(huì)產(chǎn)生任何錯(cuò)誤消息。
  3. 默認(rèn)情況下,函數(shù)的退出狀態(tài)碼是函數(shù)中最后一條命令返回的退出狀態(tài)碼
function f1 {   #function定義的函數(shù) 函數(shù)名和花括號(hào)之間必須加入空格,否則報(bào)錯(cuò)
  echo "This is an example of a function"
}
f2(){
  echo "This is second example"
}
 
for ((a=1;a<10;a++))
do
  f1        #注意函數(shù)定義要在使用函數(shù)前
  f2
done

$?的說明
$?變量會(huì)返回執(zhí)行的最后一條命令的退出狀態(tài)碼
可以在函數(shù)中指定return返回的退出狀態(tài)碼,要注意退出狀態(tài)碼的值必須在0~255之間, 任何大于256的值都會(huì)返回一個(gè)錯(cuò)誤的值

f3(){
 echo "f3"
 ls badfile  #函數(shù)的退出狀態(tài)碼是函數(shù)中最后一條命令返回的退出狀態(tài)碼
}
f3
echo "the function f3 returncode="$?
 
f4(){
  var1=3
  return $[$var1 * 3]   #return指定函數(shù)的退出狀態(tài)碼
}
f4
echo $?

參數(shù):函數(shù)使用標(biāo)準(zhǔn)的參數(shù)環(huán)境變量來代表命令行上傳給函數(shù)的參數(shù),函數(shù)名會(huì)在$0變量中定義,函數(shù)命令行上的任何參數(shù)都會(huì)通過
$1、$2等定義,也可以用特殊變量$#來判斷傳給函數(shù)的參數(shù)數(shù)目。

#向函數(shù)傳遞參數(shù)     與向腳本傳遞參數(shù)使用方式相同
addem(){
 if [ $# -eq 0 ] || [ $# -gt 2 ]
 then
    echo -1
 elif [ $# -eq 1 ]
 then
     echo $1
 else
     echo $[$1+$2]
fi
}
addem 8 9
addem 10
addem

函數(shù)中的變量:全局變量,局部變量

  • 默認(rèn)情況下,在腳本中定義的任何變量都是全局變量,可以在函數(shù)內(nèi)正常訪問,如果全局變量在函數(shù)內(nèi)被賦予了新值,那么在腳本中引用該變量時(shí),新值依然有效。
  • 在函數(shù)內(nèi)部聲明局部變量 ,只需要在變量前加入 local關(guān)鍵字。 局部變量保證了變量只局限在該函數(shù)中,如果腳本中在該函數(shù)之外有相同名字的變量,那么shell將會(huì)保持這兩個(gè)變量的值獨(dú)立。
f6(){
 temp=$[$value+5]
}
temp=4
value=6
f6
if [ $temp -gt $value ];then
 echo "temp is large"
else
 echo "temp is smaller"
fi


f7(){
 local temp=$[$value+5]
}
temp=4
value=6
f7
if [ $temp -gt $value ];then
 echo "temp is large"
else
 echo "temp is smaller"
fi

shell庫文件

在單個(gè)腳本中,使用函數(shù)可以省去一些鍵入的工作,但是在多個(gè)腳本之間如何使用同一個(gè)代碼塊呢,顯然,在每個(gè)腳本中都定義同樣的函數(shù)而只使用一次會(huì)比較麻煩。

  • shell創(chuàng)建庫文件
  • shell函數(shù)的作用域:shell只對(duì)定義它的shell會(huì)話有效。
  • source會(huì)在當(dāng)前的shell上下文中執(zhí)行命令,而不是創(chuàng)建一個(gè)新的shell來執(zhí)行命令。
  • source命令有個(gè)快捷別名,稱作點(diǎn)操作符 .
vim init.sh
#!/bin/bash
f(){
    echo "okokokok"
}
vim test7.sh
#!/bin/bash
f
source init.sh #可以全路徑引用
f

vim test7.sh
#!/bin/bash
f   #因?yàn)樽饔糜騿栴},會(huì)報(bào)錯(cuò)
. init.sh
f

exit #退出腳本命令

工作中常用小工具

防止誤刪工具(本質(zhì)是移動(dòng)目錄)

vim ~/.bashrc
trash(){
  mv $1 ~/Trash1
}
alias rm="trash"

批量修改數(shù)據(jù)并保存日志

vim  exe_targetday.sh
#!/bin/bash
set -x
source init.sh
startDay=$1
endDay=$2
if [ -z ${startDay} ]
then startDay=`date -d "-1 day" +"%Y%m%d"`
fi
 
if [ -z ${endDay} ]
then endDay=${startDay}
fi
while [ ${startDay} -le ${endDay} ]
do
  echo ${startDay}
  xqe -e "use namespace fsg_ns;alter table base_data.wappass_udi drop if exists partition(dt='${startDay}');alter table base_data.wappass_udi add partition(dt='${startDay}') location 'afs://xingtian.afs.baidu.com:9902/app/passport_log/queryengine/pass_data/wappass_udi/dt=${startDay}';" &> ${startDay}.log &
  startDay=`date -d "${startDay} 1 day" +"%Y%m%d"`
done
wait
echo "ok"

sh exe_targetday.sh 20180506 20180507

檢查文件數(shù)(check_file_num.sh)

#! /bin/sh
#
# check_file_num.sh
# Copyright (C) 2017 news_dl <news_dl@launcher-news-dl.hadoop.busdev.usw2.cmcm.com>
#
# Distributed under terms of the MIT license.
# ./check_file_num.sh s3://com.cmcm.instanews.usw2.prod/deeplearning/huangyanyan/trash/data/id_convert_path 20170309 20170322 102
 
targetPath=$1
startDay=$2
endDay=$3
fileNum=$4
while [ ${startDay} -le ${endDay} ]
do
  num=`hadoop fs -ls ${targetPath}/$startDay|wc -l`
  echo "startDay="$startDay",num="$num
  if [ "$num" -eq "$fileNum" ]
  then
    echo "ok"
  else
    echo "no"
    exit 1
  fi
  startDay=`date -d "${startDay} 1 day" +"%Y%m%d"`
done
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容