Shell基礎之函數和數組

目錄

函數

什么是函數

函數的語法

函數的調用

函數的返回值

函數的案例

函數變量的作用域

遞歸函數

函數庫文件

數組

定義數組語法

數組操作

獲取所有元素

獲取元素下標

獲取數組長度

獲取數組元素

數組添加元素

刪除數組元素

刪除數組

遍歷數組元素

數組案例


函數

什么是函數

? ? ? ? 所謂函數,與其他語言中的函數沒有太大的本質區別。它們是完成特定功能的代碼塊,這個代碼塊是可以重復使用的,并是一組命令或者語句組成

? ? ? ? 在Shell中,函數本質上就是將函數名稱與要實現的特殊功能的代碼進行引用的一種方式

在Shell中函數具有以下的優勢

把相同的程序代碼定義函數,這樣就可以重復利用,從而提長開放的效率
增加了程序代碼段的可讀性和提升管理效率
可以實現程序功能的模塊化。使得程序具備通用性

函數的語法

在Shell中,函數具有以下的語法結構:

#完整結構
function 函數名稱() {指令或語句return [返回值]
}#簡化結構
function 函數名稱 {指令或語句return [返回值]
}#進一步簡化的結構
函數名稱() {指令或語句return [返回值]
}

函數的調用

? ? ? ? 在Shell中,調用函數之前,該函數必須存在

調用函數的基本語法如下:

函數名稱 [參數1 參數2 參數3 ......]

? ? ? ? 對于函數的調用,可以有以下方法:

$#獲取參數的個數
$1、$2、$3......獲取是第幾個參數
$@ 或者 $*獲取所有的參數列表

示例:

? ? ? ? 定義一個名稱叫 fun 的函數,并且調用 fun 函數

[root@openEuler ~]# cat fun1.sh
#!/bin/bash# 定義一個名稱叫 fun 的函數
fun() {echo "the function has $# parameters"echo "all parameters $@"echo "first parameter $1"echo "second parameter $2"
}# 調用定義好的 fun 函數
fun hello world[root@openEuler ~]# bash fun1.sh 
the function has 2 parameters
all parameters hello world
first parameter hello
second parameter world
[root@openEuler ~]# 

注意:

? ? ? ? 在Shell中,函數是先定義再使用,如果是先使用再定義,就會報錯

報錯示例:

[root@openEuler ~]# cat fun1.sh
#!/bin/bash#先調用 fun 函數
fun hello world# 再定義 fun 函數
fun() {echo "the function has $# parameters"echo "all parameters $@"echo "first parameter $1"echo "second parameter $2"
}[root@openEuler ~]# bash fun1.sh 
fun1.sh: line 3: fun: command not found

? ? ? ? 如果函數只聲明了,但是沒有調用這個函數,那么該函數不會執行。但是我們可以使用 . 或者 source 來先執行這個腳本,讓函數放到當前的 Shell 環境中,此時我們在 Shell 環境中就可以執行這個函數

示例:

[root@openEuler ~]# cat fun1.sh
#!/bin/bash#只聲明 fun 函數,但是沒調用函數
fun() {echo "the function has $# parameters"echo "all parameters $@"echo "first parameter $1"echo "second parameter $2"
}#將腳本中的函數放到當前shell 環境中
[root@openEuler ~]# source ./fun1.sh [root@openEuler ~]# fun 1 2
the function has 2 parameters
all parameters 1 2
first parameter 1
second parameter 2

函數的返回值

? ? ? ? 在 Shell 中,函數也是可以有返回值的,但是它和其他語言中的函數返回值不太相同

在函數中如果使用 return 語句來退出函數,并返回函數的值時,那么在函數外就需要使用 echo $? 來獲取返回的值
在函數中如果使用的是 echo 輸出,那么在函數外邊就可以使用 變量=$(函數名稱) 來獲取返回的值

注意:

? ? ? ? 在 Shell 中使用 return 返回的只能是整數值,而且范圍不能超過0~255,如果超過了則需要與256取模

示例1:

? ? ? ? 計算兩個參數的和

[root@openEuler ~]# cat fun2.sh 
#!/bin/bash
sum1() {sum=$[$1 + $2]echo $sum
}
read -p "Please enter first number: " first
read -p "Please enter second number: " secondsum1 first second
#或者
res=$(sum1 first second)echo $res[root@openEuler ~]# bash fun2.sh 
Please enter first number: 6     
Please enter second number: 4
10

示例2:

? ? ? ? 獲取字符串的長度

[root@openEuler ~]# cat fun3.sh 
#!/bin/bash
length() {str=$1len=0if [ "$1" != "" ]; thenlen=${#str}fi      return $len
}       
length "abc123"
echo "the string's length is $?"[root@openEuler ~]# bash fun3.sh 
the string's length is 6

函數的案例

示例1:

? ? ? ? 將一個點分十進制格式的IP地址轉換成點分二進制格式

比如:255.255.255.255 ——> 11111111.11111111.11111111.11111111

[root@openEuler ~]# cat fun4.sh 
#!/bin/bashdecimal_to_bin() {NUM=$1for i in {1..8}doSUM=$[NUM % 2]$SUMlet NUM/=2#((NUM=NUM/2))doneecho $SUM
}split_ip() {IP=$1for i in {1..4}donum=${IP%%.*}    # IP=192.168.72.150     -> num=192#echo "num=$num"IP=${IP#*.} # IP=168.72.150    delete 192#echo "ip=$IP"BIN=$(decimal_to_bin num)#decimal_to_bin $numecho -n $BINdone
}read -p "Please enter a valid IP address: " INIPres=$(split_ip $INIP)
echo ${res%.*}[root@openEuler ~]# bash fun4.sh 
Please enter a valid IP address: 192.168.72.112
11000000.10101000.01001000.01110000

示例2:

? ? ? ? 編寫一個腳本,實現判斷給定的 IP 地址范圍 [192.168.72.130~192.168.72.140] 是否在線

[root@openEuler ~]# cat fun5.sh
#!/bin/bashonline() {for i in {148..152}do      if ping -c1 192.168.72.$i &>/dev/nullthen    echo "192.168.72.$i is up"else    echo "192.168.72.$i is unknow"fi      done    
}       online[root@openEuler ~]# bash fun5.sh
192.168.72.148 is unknow
192.168.72.149 is unknow
192.168.72.150 is up
192.168.72.151 is up
192.168.72.152 is unknow

函數變量的作用域

示例1:

? ? ? ? 函數的變量是全局變量

[root@openEuler ~]# cat fun6.sh 
#!/bin/bashstr="hello shell"
func() {str="openlab"echo $strstr2="hello"
}
echo "$str"
func
echo "$str"
echo "$str2"[root@openEuler ~]# bash fun6.sh 
hello shell
openlab
openlab
hello

注意:

? ? ? ? 使用?$() 這種方式來執行命令時,變量值還是需要使用 $ 變量名的方式來獲取,當使用 $(())來做算術運算時,可以省略 $ 而直接使用變量名

示例:

#!/bin/basha=1
b=2
c=$[ $a + $b ] #`$a+$b`echo `expr $a + $b`echo $(expr $a + $b)echo $cd=$((a+b))
echo $d

示例2:

? ? ? ? 函數的變量如果希望是局部的,那么我們需要顯式的使用 local 來聲明

[root@openEuler ~]# cat fun7.sh 
#!/bin/bashs="ni hao"
func() {local s="ni ye hao"echo $slocal s1="da jia wang shang hao"
}
echo "$s"
func
echo "$s"
echo "${s1}"
[root@openEuler ~]# bash fun7.sh 
ni hao
ni ye hao
ni hao[root@openEuler ~]# 

注意:

? ? ? ? 當使用 local 來聲明變量時,它就是一個局部變量,離開函數后,這個變量就消失了

遞歸函數

示例1:

? ? ? ? 根據用戶輸入的數值計算該數的階乘

[root@openEuler ~]# cat recursion.sh 
#!/bin/bashrecursion() {if [ $1 -eq 1 ] ; thenresult=1elif [ $1 -gt 1 ] ; thenlocal n=$[ $1 - 1 ]recursion $nlet "result=$1 * $?"elseecho "The number is invalid"fireturn $result
}recursion $1
echo $?[root@openEuler ~]# bash recursion.sh 5
120

示例2:

? ? ? ? 使用函數遞歸 /var/log 目錄,如果是文件直接輸入文件名,如果是目錄則輸出目錄名稱并且輸出目錄下所有子目錄和文件名

[root@openEuler ~]# cat fact.sh 
#!/bin/bashlist_file() {for f in $(ls $1)doif [ -d "$1/$f" ]; then #/var/log/anacondaecho "$2 directory $f"list_file "$1/$f" "├── $2"elseecho "$2 file $f"fidone
}
list_file $1 "├── "[root@openEuler ~]# bash fact.sh /var/log
├──  directory anaconda
├── ├──  file anaconda.log
├── ├──  file dbus.log
├── ├──  file dnf.librepo.log
├── ├──  file hawkey.log
├── ├──  file journal.log
├── ├──  file lorax-packages.log
├── ├──  file lvm.log
├── ├──  file packaging.log
├── ├──  file program.log
├── ├──  file storage.log
├── ├──  file syslog
├── ├──  file X.log
├──  directory audit
├── ├──  file audit.log
├──  file boot.log
├──  file boot.log-20240324
........

函數庫文件

示例:

? ? ? ? (1)創建庫文件

[root@openEuler ~]# cat function_library.sh 
#!/bin/bashaddition() {echo $[$1 + $2]
}substraction() {echo $[$1 - $2]
}multipication() {echo $[$1 * $2]
}division() {if [ $2 -eq 0 ]; thenecho "Division cannot be 0"elseecho $[$1 / $2]fi
}factorial() {if [ $1 -eq 1 ]; thenecho 1elif [ $1 -gt 1 ]; thenlocal tmp=$[$1-1]local res=$(factorial $tmp)echo $[$1 * res]elseecho "input value invalid"fi
}

? ? ? ? (2)在腳本中加載函數庫文件并且使用

[root@openEuler ~]# cat fl_test.sh 
#!/bin/bash# load function_library.sh
source /root/function_library.shv1=10
v2=5r1=$(addition $v1 $v2)
r2=$(substraction $v1 $v2)r3=$(factorial $v2)echo $r1
echo $r2
echo $r3[root@openEuler ~]# bash fl_test.sh 
15
5
120

數組

? ? ? ? 所謂數組,就是指將具有相同類型的若干變量按照一定的順序組織在一起的一種數據類型

定義數組語法

用小括號將變量值括起來賦值給數組變量,每個變量之間用空格分隔array=(value1 value2 value3 ...... valuen)
使用小括號將變量值括起來,并且采用鍵值對的形式賦值array=([0]=one [1]=two ...... [n-1]=valuen)
分別定義數組變量的值array[0]=one;array[1]=two;......array[n]=valuen
使用動態的定義變量,并使用命令的輸出結果作為數組的內容array=(命令)
通過 declare 語句來定義數組declare -a array

數組操作

獲取所有元素

# 聲明數組,數組的名稱為 array,它里面有 6 個元素,分別是 1,2,3,4,5,6
[root@openEuler ~]# array=(1 2 3 4 5 6)
# 獲取數組所有無素,需要注意使用大括號將整個數組包起來
[root@openEuler ~]# echo $array[*]
1[*]
[root@openEuler ~]# echo ${array[*]}
1 2 3 4 5 6
[root@openEuler ~]# echo ${array[@]}
1 2 3 4 5 6

獲取元素下標

# 定義數組,數組的名稱為 array,它的第一個元素是 hello,第二個元素是 shell,第三個元素是 python
[root@openEuler ~]# array=([0]="hello" [1]="shell" [2]="python")
# 通過 !數組名稱[*|@] 來獲取元素對應的下標
[root@openEuler ~]# echo ${!array[@]}
0 1 2
[root@openEuler ~]# echo ${!array[*]}
0 1 2

獲取數組長度

# 定義數組,使用的是第三種語法
[root@openEuler ~]# array[0]="zhangsan"; array[1]="lisi"; array[2]="wangwu"
# 獲取數組中第一個元素的長度
[root@openEuler ~]# echo ${#array}
8
# 獲取數組元素個數(數組長度)
[root@openEuler ~]# echo ${#array[*]}
3
[root@openEuler ~]# echo ${#array[@]}
3

獲取數組元素

# 使用第四種語法:數組名稱=(命令) 來創建數組,然后通過下標獲取對應的元素
[root@openEuler ~]# array=(`seq 5`)
# 獲取數組中所有元素
[root@openEuler ~]# echo ${array[*]}
1 2 3 4 5
# 獲取數組中下標為 3 所對應的元素,如果存在則返回該下標對應的元素,如果不存在則返回空
[root@openEuler ~]# echo ${array[3]}
4
[root@openEuler ~]# echo ${array[6]}[root@openEuler ~]# echo $?
0

數組添加元素

# 使用第五種語法來定義數組,數組的名稱為 array
[root@openEuler ~]# declare -a array
# 給數組下標為0的位置添加元素
[root@openEuler ~]# array[0]=50
# 給數組下標為1的位置添加元素
[root@openEuler ~]# array[1]=35
# 給數組下標為2的位置添加元素
[root@openEuler ~]# array[20]=28
# 獲取數組中所有元素
[root@openEuler ~]# echo ${array[*]}
50 35 28# 使用 -A 的方式來定義數組
[root@openEuler ~]# declare -A arr
[root@openEuler ~]# arr[one]=15
[root@openEuler ~]# arr[two]=20
[root@openEuler ~]# arr[thr]=30
[root@openEuler ~]# echo ${arr[@]}
30 20 15# 獲取下標對應的元素
[root@openEuler ~]# echo ${array[1]}
35
[root@openEuler ~]# echo ${arr[two]}
20

刪除數組元素

# 定義數組
[root@openEuler ~]# array=(10 20 30 40 50)
# 獲取數組中所有元素
[root@openEuler ~]# echo ${array[@]}
10 20 30 40 50
# 刪除數組中下標為2的元素
[root@openEuler ~]# unset array[2]
# 驗證是否已經刪除
[root@openEuler ~]# echo ${array[*]}
10 20 40 50
[root@openEuler ~]# echo ${#array[*]}
4

刪除數組

# 定義數組
[root@openEuler ~]# array=(10 20 30 40 50)
# 獲取數組長度
[root@openEuler ~]# echo ${#array[*]}
5
# 刪除數組
[root@openEuler ~]# unset array
# 驗證數組是否刪除
[root@openEuler ~]# echo ${#array[@]}
0

遍歷數組元素

[root@openEuler ~]# cat array.sh
#!/bin/bashfiles=(`ls $1`)
for((i=0;i<${#files[*]};i++)); doecho ${files[$i]}
done[root@openEuler ~]# bash array.sh 
array.sh
fact.sh
fl_test.sh
fun1.sh
fun2.sh
fun3.sh
fun4.sh
fun5.sh
fun6.sh
fun7.sh
function_library.sh
ips
myfile
mytest.sh
recursion2.sh
recursion.sh

數組案例

示例1:

? ? ? ? 從標準輸入讀取 n 次字符串,每次輸入的字符串保存在數組 array 中

[root@openEuler ~]# cat array1.sh 
#!/bin/bash
i=0
n=5
while [ "$i" -lt $n ]; doecho "Please input string... `expr $i + 1`"read array[$i]b=${array[$i]}echo "$b"i=`expr $i + 1`
done
[root@openEuler ~]# bash array1.sh 
Please input string... 1
1
1
Please input string... 2
2
2
Please input string... 3
3
3
Please input string... 4
4
4
Please input string... 5
5
5

示例2:

? ? ? ? 將字符串中的字母逐個放入數組,并輸出到標準輸出

#!/bin/bashstrs="helloworldshell"
declare -a arrayfor ((i=0;i<${#strs};i++)); doarray[$i]=${strs:$i:1}
donefor i in ${array[@]}; doecho ${i}
done

示例3:

? ? ? ? 將1~3這3個數字存到數組中,分別乘以8后再依次輸出

#!/usr/bin/basharray=(`seq 3`)for ((i=0; i<${#array[@]}; i++)); doecho $[${array[$i]}*8]
done

示例4:

? ? ? ? 輸出如下內容中字母數不大于6的單詞

cat is favorite to eat fish

#!/bin/basharray=(cat is favorite to eat fish)for i in ${array[*]}; doif [ ${#i} -le 6 ]; thenecho $ifi      
done

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/44676.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/44676.shtml
英文地址,請注明出處:http://en.pswp.cn/web/44676.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

解決pycharm無法識別miniconda

解決pycharm無法識別miniconda 找到miniconda安裝目錄下condabin/conda.bat文件&#xff0c;點擊load即可識別codna環境 a環境

Spring Boot(七十九):SprngBoot整合Apache tika做文件類型檢測

之前有一個章節介紹了Apache tika實現文檔內容解析,地址如下:Spring Boot(六十八):SpringBoot 整合Apache tika 實現文檔內容解析_springboot tika pptx-CSDN博客 下面我們介紹Apache tika實現文件類型檢測 1 引入依賴 <dependency><groupId>org.apache.tika&…

Docker 掛載目錄空間占滿修改/var/lib/docker/overlay2 的路徑解決方案

本文詳細描述了在CentOS7系統中卸載舊版Docker、安裝依賴、添加Docker源、配置存儲路徑并啟動Docker&#xff0c;使其在/home目錄下運行的過程。 以下是在CentOS 7下重新安裝Docker并將其安裝在/home/下的完整步驟&#xff1a; 卸載舊版本的Docker。如果您之前已經安裝了Dock…

仕考網:沒有學位證能考公務員嗎?

公務員考試需要滿足報名條件才能參加&#xff0c;沒有學位證能考公嗎? 沒有學位證書的考生也有機會參與公務員考試雖然可以選擇的崗位比較少&#xff0c;但可以報考參加那些不設定學位要求的崗位。當發布的公務員招錄信息中某一職位的學位要求標注為“無要求”時&#xff0c;…

【C++】:繼承[下篇](友元靜態成員菱形繼承菱形虛擬繼承)

目錄 一&#xff0c;繼承與友元二&#xff0c;繼承與靜態成員三&#xff0c;復雜的菱形繼承及菱形虛擬繼承四&#xff0c;繼承的總結和反思 點擊跳轉上一篇文章&#xff1a; 【C】&#xff1a;繼承(定義&&賦值兼容轉換&&作用域&&派生類的默認成員函數…

MATLAB Gazebo聯合仿真

準備仿真環境&#xff1a;在Gazebo中設置仿真場景&#xff0c;包括機器人模型、環境布局、傳感器和執行器等。編寫MATLAB腳本&#xff1a;在MATLAB中編寫控制算法和數據處理腳本&#xff0c;用于接收Gazebo中的傳感器數據&#xff0c;并生成控制命令。建立通信&#xff1a;通過…

DEBUG:jeston卡 遠程ssh編程

問題 jeston 打開網頁 gpt都不方便 而且只需要敲命令就行 解決 下載MobaXterm(window執行) liunx需要虛擬機 軟件 遠程快速復制命令

PHP文字ocr識別接口示例、人工智能的發展

全球在人工智能升級的大背景下&#xff0c;有一定規模的制造商開始大量部署人工智能機器人、系統&#xff0c;以此取代危險、簡單和重復性的工作。各種人工智能技術的迅猛發展&#xff0c;正在驅動各行業就業市場發現變革。 京東物流大家并不陌生&#xff0c;京東快遞機器人在…

vue中table內容和lable對不齊解決方案

問題&#xff1a; 代碼片段&#xff1a; <template><el-table :data"tableData" stripe style"width: 100%"><el-table-column prop"title" label"標題" width"80px" /><el-table-column prop"n…

Windows安全日志導致環境內存占用過高

Windows 環境內存占用高不釋放&#xff0c;目前遇到的常見情況如下&#xff1a; 情況一&#xff1a;JVM內存泄漏 這種網上的排查方式有很多&#xff0c;自行查閱即可 情況二&#xff1a;SQLserver內存配置過大 這種也是&#xff0c;從網上查找修改方式然后修改即可 情況三…

python的面向對象編程

為什么要面向對象編程&#xff1f; 偉大的領袖毛澤東曾說過&#xff1a;編程最大的敵人是重復。 最開始&#xff0c;在程序中寫的一條條語句&#xff0c;在執行的時候會變成一條條指令交給CPU執行。這就是**“程序是指令的集合”** 。為了簡化程序的設計&#xff0c;引入了函數…

WebPages 全局:深入解析現代網頁設計與開發

WebPages 全局:深入解析現代網頁設計與開發 引言 隨著互聯網技術的飛速發展,網頁設計與開發已經成為了數字化時代的重要組成部分。從簡單的文本和圖像展示,到如今復雜的多媒體交互體驗,網頁設計經歷了翻天覆地的變化。本文將深入探討WebPages全局,包括網頁設計的基本概念…

Defensor 4.5:構建數據資產為中心的安全運營體系

5月31日“向星力”未來數據技術峰會上&#xff0c;星環科技重磅發布數據安全管理平臺 Defensor 4.5版本。新版本引入了以數據資產為中心的數據安全運營體系&#xff0c;通過智能化大模型技術&#xff0c;幫助企業快速、精準地識別核心重要資產&#xff1b;建設全局的數據安全策…

pytorch GPU cuda 使用 報錯 整理

GPU 使用、報錯整理 1. 使用指定GPU&#xff08;單卡&#xff09;1.1 方法1&#xff1a;os.environ[CUDA_VISIBLE_DEVICES]1.2 方法2&#xff1a;torch.device(cuda:2)1.3 報錯1&#xff1a;RuntimeError: CUDA error: invalid device ordinal CUDA kernel errors might be asy…

MySQL學習記錄 —— ?? 常用程序和配置文件

文章目錄 1、mysqld2、mysql常用命令介紹 3、配置文件語法 1、mysqld mysqld就是MySQL服務器&#xff0c;是一個多線程程序。對數據目錄&#xff0c;即mysql的主要工作目錄進行訪問管理。當mysqld啟動時&#xff0c;會偵聽指定的端口&#xff0c;處理來自客戶端程序的網絡連接…

【vue教程】二. Vue特性原理詳解

目錄 回顧本章涵蓋知識點Vue 實例和選項創建 Vue 實例Vue 實例的選項 Vue 模板語法插值表達式指令v-bindv-modelv-on 自定義指令創建自定義指令在模板中使用自定義指令自定義指令的鉤子函數自定義指令的實例演示 指令注冊局部注冊指令過濾器 數據綁定和響應式原理響應式數據綁定…

Oracle邏輯備份

邏輯備份 expdp 備份恢復表空間 創建測試數據 # 創建表空間 create tablespace itpux01 datafile /oradata/fghsdb/itpux01.dbf size 100m autoextend off extent management local autoallocate segment space management auto; create tablespace itpux02 datafile /o…

編程題目積累(day5)

題目&#xff1a; 源數組a&#xff0c;將a中所有元素乘以2之后添加進a&#xff0c;則這個a就叫雙倍數組&#xff0c;給你一個數組a&#xff0c;判斷它是不是雙倍數組&#xff0c;如果是則輸出源數組&#xff0c;不是則輸出空數組。 補充知識&#xff1a; python中枚舉和字典…

OAuth 和 SSO 場景中的 URL 語法解析

OAuth 和 SSO 場景中的 URL 語法解析 在 OAuth 和 SSO (Single Sign-On) 場景中&#xff0c;URL 是一個關鍵組件&#xff0c;用于在客戶端和服務器之間傳遞認證請求和響應。讓我們深入解析這個 URL&#xff1a; https://api.commerce.ondemand.com/occ/oauth/authorize?resp…

【python數據結構精講】雙端隊列

通過總結《流暢的Python》等書中的知識&#xff0c;總結Python中常用工具的方法。 deque&#xff0c;學名雙端隊列。 1. 常用方法 append()&#xff1a;隊列尾部添加appendleft()&#xff1a;隊首添加pop()&#xff1a;移除隊列最后一個元素popleft()&#xff1a;移除隊列第一…