Shell腳本中select、函數總結

描述:

select控制語句基于Korn Shell中的控制結構

select語句首先顯示一個菜單,然后根據用戶的選擇給變量賦予相應的值,最后執行一系列命令。

語法:

select varname [ in arg…]

do

   commands

done

說明:

select結構顯示arg項的菜單。加入忽略關鍵字in和參數列表,select控制語句就用位置參數來取代arg項。select的菜單格式化為在每一項前加一個數字。

select循環主要用于創建菜單,按數字順序排列的菜單項顯示在標準輸出上,并顯示PS3提示符,等待用戶輸入

用戶輸入菜單列表中的某個數字,執行相應的命令。

用戶輸入被保存在內置變量REPLY中。

select是個無限循環,使用break命令退出循環,或用exit命令終止腳本,也可以按ctrl+c推出循環

select經常和case聯合使用

與for循環類似,可以省略in list,此時使用位置參數

示例:

#!/bin/bash
PS3="Please guss which fruit I like:"
select var in "apple" "pear" "orange" "peach";do
  if [ "$var" == "apple" ];then
    echo "You are right"
    break
  else
    echo "try again"
  fi  
done
[root@localhost ~]# bash a.sh 
1) apple
2) pear
3) orange
4) peach
Please guss which fruit I like:2
try again
Please guss which fruit I like:3
try again
Please guss which fruit I like:4
try again
Please guss which fruit I like:1
You are right

函數:

函數(function)是由若干條shell命令組成的語句塊,實現代碼重用和模塊化編程,

它與shell程序形式上是相似的,不同的是它不是一個單獨的進程,不能獨立運行,而是shell程序的一部分

函數和shell程序的區別在于:

shell程序在子shell中運行,而shell函數在當前shell中運行。因此在當前shell中,函數可以對shell中的變量進行修改

函數由兩部分組成:函數名和函數體

語法一:

function NAME {

  函數體

}

語法二:

NAME() {

  函數體

}

函數的使用:

可以在交互式環境下定義函數

可將函數放在腳本文件中作為它的一部分

可放在只包含函數的單獨文件中

調用:函數只有被調用才會執行

   調用:給定函數名

       函數名出現的地方,會被自動替換為函數代碼

函數的生命周期:被調用時創建,返回時終止

函數的執行結果返回值:

  1,使用echo或printf命令進行輸出

  2,函數體調用命令的輸出結果

函數的退出狀態碼:

  1,默認取決于函數最后一條命令的退出狀態碼

  2,自定義退出狀態碼,其格式為:

  return 從函數中返回,用最后狀態命令決定返回值

  return 0 正確返回

  return 1-255 有錯誤返回

交互式環境下定義和使用函數

示例:

[root@localhost ~]# dir(){   
> ls -l            定義該函數后,在命令行直接鍵入dir,其顯示結果同ls -l的作用相同
> }
[root@localhost ~]# dir
-rw-r--r--. 1 root root  205 Aug 19 17:55 a.sh
-rwxr-xr-x. 1 root root  106 Aug 12 05:42 backup.sh
drwxr-xr-x. 2 root root 4096 Aug 15 06:28 bin
[root@localhost ~]# unset dir    從當前系統中退出該dir函數

在腳本中定義及使用函數

函數在使用前必須定義,因此應該將函數定義放在腳本開始部分,直到shell首次發現它后才能使用

調用函數僅使用其函數名即可

示例:

[root@localhost ~]# cat func1
#!/bin/bash
#func1
hello(){
echo "Hello there today's date is `date +%F`"
}
echo "now going to the function hello"
hello
echo "back from the function"
[root@localhost ~]# chmod +x func1
[root@localhost ~]# ./func1
now going to the function hello
Hello there today's date is 2016-08-21
back from the function

使用函數文件

可以將經常使用的函數存入函數文件,然后將函數文件載入shell

文件名可任意取,但最后與相關任務有某種聯系。例如:functions.main

一旦函數文件載入shell,就可以在命令行或腳本中調用函數??梢允褂胹et命令查看所有定義的函數,其輸出列表包括已經載入shell的所有函數

若要改動函數,首先用unset命令從shell中刪除函數。改動完畢后,再重新載入此文件

創建函數文件:

示例:

[root@localhost ~]# cat function.main       函數文件
#!/bin/bash
#functions.main
findit() {
  if [ $# -lt 1 ];then
    echo "Usage:findit file"
    return 1
  fi
  find / -name $1 -print
}

函數文件已創建好后,要將它載入shell

定位函數文件并載入shell格式:

  . filename 或 source filename   (即<點> <空格> <文件名>)   (這里的文件名要帶正確路徑)

使用set命令檢查函數是否已載入。set命令將在shell中顯示所有已載入的函數

[root@localhost ~]# . function.main
[root@localhost ~]# set
findit () 
{ 
    if [ $# -lt 1 ]; then
        echo "Usage:findit file";
        return 1;
    fi;
    find / -name $1 -print
}
[root@localhost ~]# findit groups   執行shell函數,鍵入函數名即可
/usr/bin/groups
[root@localhost ~]# unset findit     刪除shell函數(命令格式為:unset function_name)
[root@localhost ~]# set     函數findit無顯示

函數參數:

傳遞參數給函數:調用函數時,在函數名后面以空白分隔給定參數列表即可;例如:"findit a b …"

在函數體中當中,可使用$1,$2,…調用參數,還可以使用$@,$*,$#等特殊變量

函數變量:

  環境變量:當前shell和子shell有效

  本地變量:只在當前shell進程有效,為執行腳本會啟動專用子shell進程;因此,本地變量的作用范圍是當前shell腳本程序文件,包括腳本中的函數

  局部變量:函數的生命周期;函數結束時變量被自動銷毀

  注意:如果函數中有局部變量,如果其名稱同本地變量,使用局部變量

  在函數中定義局部變量的方法: local NAME=VALUE

函數遞歸示例:

[root@localhost ~]# cat fact.sh 
#!/bin/bash
fact() {
  if [ $1 -eq 0 -o $1 -eq 1 ];then
echo 1
  else
echo $[$1*$(fact $[$1-1])]
  fi
}
fact 4
[root@localhost ~]# bash -x fact.sh 
+ fact 4
+ '[' 4 -eq 0 -o 4 -eq 1 ']'
++ fact 3
++ '[' 3 -eq 0 -o 3 -eq 1 ']'
+++ fact 2
+++ '[' 2 -eq 0 -o 2 -eq 1 ']'
++++ fact 1
++++ '[' 1 -eq 0 -o 1 -eq 1 ']'
++++ echo 1
+++ echo 2
++ echo 6
+ echo 24
24

作業:

1、寫一個服務腳本/root/bin/testsrv.sh,完成如下要求

(1) 腳本可接受參數: start, stop, restart, status

(2) 如果參數非此四者之一,提示使用格式后報錯退出

(3) 如是start:則創建/var/lock/subsys/SCRIPT_NAME, 并顯示“啟動成功”

考慮:如果事先已經啟動過一次,該如何處理?

(4) 如是stop:則刪除/var/lock/subsys/SCRIPT_NAME, 并顯示“停止完成”

考慮:如果事先已然停止過了,該如何處理?

(5) 如是restart,則先stop, 再start

考慮:如果本來沒有start,如何處理?

(6) 如是status, 則如果/var/lock/subsys/SCRIPT_NAME文件存在,則顯示

“ SCRIPT_NAME is running…”

如果/var/lock/subsys/SCRIPT_NAME文件不存在,則顯示“ SCRIPT_NAME

is stopped…”

其中: SCRIPT_NAME為當前腳本名

[root@localhost function]# cat testsrv.sh 
#!/bin/bash
fstart () {
  if [ -e "$1" ];then
     echo "Already Start"
  else
     touch $File
     echo "Start Successfully!"
  fi
}
fstop() {
  if [ -e "$1" ];then
     rm -f $File
     echo "Stop Successfully!"
  else
     echo "Already stop"
  fi
}
frestart() {
  if [ -e "$1" ];then
     fstop &> /dev/null
     fstart &> /dev/null
     echo "Restart Successfully!"
  else
     fstart &> /dev/null
     echo "Start Successfully!"
  fi
}
fstatus() {
  if [ -e "$1" ];then
     echo "testsrv is running"
  else
     echo "testsrv has been stop"
  fi
}
select choice in start stop restart status quit;do
  File=/var/lock/subsys/testsrv.sh
    case $choice in
    start)
       fstart $File
       ;;
    stop)
       fstop $File
       ;;
    restart)
       frestart $File
       ;;
    status)
       fstatus $File
       ;;
    quit)
       break
       ;;
     *)
       echo "error,please choose again"
       exit 2
     esac
done 
[root@localhost function]# bash testsrv.sh 
1) start
2) stop
3) restart
4) status
5) quit
#? 4
testsrv is running
#? 3
Restart Successfully!
#? 1
Already Start
#? 2
Stop Successfully!
#? 5

2、編寫一個腳本/root/bin/copycmd.sh

(1) 提示用戶輸入一個可執行命令名稱;

(2) 獲取此命令所依賴到的所有庫文件列表

(3) 復制命令至某目標目錄(例如/mnt/sysroot)下的對應路徑下;

如: /bin/bash ==> /mnt/sysroot/bin/bash

/usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd

(4) 復制此命令依賴到的所有庫文件至目標目錄下的對應路徑下:

如: /lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ldlinux-x86-64.so.2

(5)每次復制完成一個命令后,不要退出,而是提示用戶鍵入新的要復制的命

令,并重復完成上述功能;直到用戶輸入quit退出

[root@localhost ~]# cat copycmd.sh 
#!/bin/bash
ch_root="/mnt/sysroot/"
[ ! -d $ch_root ] && mkdir $ch_root
bincopy() {
   if which $1 &>/dev/null;then
      local cmd_path=`which --skip-alias $1`
      local bin_dir=`dirname $cmd_path`
      [ -d ${ch_root}${bin_dir} ] || mkdir -p ${ch_root}${bin_dir}
      [ -f ${ch_root}${cmd_path} ] || cp $cmd_path ${ch_root}${bin_dir}
      return 0
   else
      echo "Command not found"
      return
   fi
}
libcopy() {
   local lib_list=$(ldd `which --skip-alias $1` | grep -Eo '/[^[:space:]]+')
   for loop in $lib_list;do
       local lib_dir=`dirname $loop`
       [ -d ${ch_root}${lib_dir} ] || mkdir -p ${ch_root}${lib_dir}
       [ -f ${ch_root}${loop} ] || cp $loop ${ch_root}${lib_dir}
   done
}
read -p "Please input a command:" command
while [ "$command" != "quit" ];do
    if bincopy $command;then
         libcopy $command
    fi
    read -p "Please input a command or quit:" command
done
[root@localhost ~]# ll /mnt/sysroot/lib64
-rwxr-xr-x. 1 root root  164432 Aug 23 15:28 ld-linux-x86-64.so.2
-rwxr-xr-x. 1 root root   37056 Aug 23 15:28 libacl.so.1
-rwxr-xr-x. 1 root root   19888 Aug 23 15:28 libattr.so.1
-rwxr-xr-x. 1 root root   20024 Aug 23 15:28 libcap.so.2
-rwxr-xr-x. 1 root root 2107816 Aug 23 15:28 libc.so.6
-rwxr-xr-x. 1 root root   19512 Aug 23 15:28 libdl.so.2
-rwxr-xr-x. 1 root root  153192 Aug 23 15:28 liblzma.so.5
-rwxr-xr-x. 1 root root  398272 Aug 23 15:28 libpcre.so.1
-rwxr-xr-x. 1 root root  142296 Aug 23 15:28 libpthread.so.0
-rwxr-xr-x. 1 root root  147120 Aug 23 15:28 libselinux.so.1
[root@localhost ~]# ll /mnt/sysroot/usr/bin
-rwxr-xr-x. 1 root root  54048 Aug 23 15:41 cat
-rwxr-xr-x. 1 root root 117616 Aug 23 15:35 ls

3、寫一個函數實現兩個數字做為參數,返回最大值

#!/bin/bash
function NUMBER {
 if [ $1 -lt $2 ];then
    echo "The max number is $2"
 elif [ $1 -eq $2 ];then
    echo "The two number is equal"
 else
    echo "The max number is $1"
 fi
}
NUMBER $1 $2
[root@localhost function]# bash test3.sh 3 5
The max number is 5
[root@localhost function]# bash test3.sh 6 4
The max number is 6
[root@localhost function]# bash test3.sh 8 8
The two number is equal

4、寫一個函數實現數字的加減乘除運算,例如輸入 1 + 2,將得出正確結果

[root@localhost function]# cat test4-1.sh 
#!/bin/bash
fjia() {
   sum=$[$1+$2]
   echo "$sum"
}
fjian() {
   sum=$[$1-$2]
   echo "$sum"
}
fcheng() {
   sum=$[$1*$2]
   echo "$sum"
}
fchu() {
   sum=$[$1/$2]
   echo "$sum"
}
read -p "please input: " a b c
   case $b in
   +)
      fjia $a $c
      ;;
   -)
      fjian $a $c
      ;;
   \*)
      fcheng $a $c
      ;;
   /)
      fchu $a $c
      ;;
   *)
      echo "please input correct form"
      exit 3
   esac
[root@localhost function]# bash test4-1.sh 
please input: 6+7
please input correct form
please input: 6 + 7
13 
please input: 6 - 8   
-2
please input: 2 * 3
6
please input: 4 / 2
2

5、斐波那契數列又稱黃金分割數列,因數學家列昂納多·斐波那契以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列: 0、 1、 1、 2、 3、 5、 8、 13、 21、 34、 ……,斐波納契數列以如下被以遞歸的方法定義: F( 0) =0, F( 1) =1, F( n) =F(n-1)+F(n-2)(n≥2)

寫一個函數,求n階斐波那契數列

[root@localhost function]# cat test5-1.sh 
#!/bin/bash
ftzsl() {
   if [ $1 -eq 0 ];then
      echo "0"
   elif [ $1 -eq 1 ];then
      echo "1"
   else
      echo "$[$(ftzsl $[$1-1])+$(ftzsl $[$1-2])]"
   fi
}
read -p "please input a number: " n
   ftzsl $n
[root@localhost function]# bash test5-1.sh 
please input a number: 5
5 
please input a number: 6
8

6、漢諾塔(又稱河內塔)問題是源于印度一個古老傳說。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。并且規定,在小圓盤上不能放大圓盤,在三根柱子之間

一次只能移動一個圓盤。利用函數,實現N片盤的漢諾塔的移動步驟

[root@localhost function]# cat test6.sh 
#!/bin/bash
fpan() {
  if [ $1 -eq 1 ];then
     echo "$2 ==> $4"
  else
     fpan $[$1-1] $2 $4 $3
          echo "$2 ==> $4"
     fpan $[$1-1] $3 $2 $4
  fi
}
fpan $1 a b c 
[root@localhost function]# bash test6.sh 2
a ==> b
a ==> c
b ==> c

原創文章,作者:pingsky,如若轉載,請注明出處:http://www.www58058.com/38881

(0)
pingskypingsky
上一篇 2016-08-24
下一篇 2016-08-24

相關推薦

  • 上古神器vim

    概述:     在之前的篇章中,我們介紹了一些文本的處理工具,如grep、sed、cut、sort等,但是那些工具的側重點都在于有了現成的文本之后,對現有的文本進行一定條件的加工處理后,滿足我們進一步對數據的要求。但是目前為止,還沒有接觸一款專業用來編輯文本的工具,本篇就來介紹一下Linux系統上自帶的專業用來文本編輯…

    Linux干貨 2016-08-10
  • N25 – Week 4 blog

    第四周博客作業了,感覺前面的有好多都忘掉了,但是沒有時間補以前的啊……好郁悶,幸好今天周五,明天又是圣誕節,從馬云爸爸買了一顆圣誕樹,今晚回家裝上 1. 復制/etc/skel目錄為/home/tuser1,要求/home/tuser1及其內部文件的屬組和其他用戶均沒有任何訪問權限 [root@dhcp-10-129-6-166&nb…

    Linux干貨 2016-12-20
  • TCP三次握手和四次揮手

    TCP三次握手 有兩臺機器,A是客戶端(主動發起請求的人),B是服務器端(被動接受請求的人),客戶端A剛開始沒有人和他通訊,所以客戶端A的狀態是CLOSDE(關閉的),服務器端B剛開始的狀態也是CLOSDE,但是總有人去訪問他,所以服務器端B開啟了LISTEN(收聽)狀態。 (1)假設A機器想鏈接B機器了,他就會向B機器發送一個建立鏈接的請求,這個建立鏈接請…

    2017-08-31
  • 基于lvs調度的web應用——Discuz程序

    實驗環境: 前端主機:10.1.43.101 后端主機1:172.16.0.9   作為lvs-dr的調度器,并且提供mysql和nfs文件共享 后端主機2:172.16.0.2   作為ap服務器之一 后端主機3:172.16.0.3   作為ap服務器之一 實驗拓撲: 后端主機1: [root@node3…

    Linux干貨 2016-10-26
  • 文本處理sed

    文本處理sed Sed介紹:          處理文本的工具sed ,Stream EDitor, 行編輯器 sed是一種流編輯器,它一次處理一行內容。處理時,把當前處理的行存儲在臨時緩沖區中,稱為“模式空間”(pattern space),接著用sed命令處理緩沖區中的內容,…

    Linux干貨 2017-05-04
欧美性久久久久