linux-shell腳本

linux-shell腳本

  • 一、什么是shell腳本?
  • 二、為什么要學習shell腳本?
  • 三、腳本執行的方式
    • 3.1 bash test.sh
    • 3.2 ./test.sh
    • 3.3 source test.sh
    • 3.4 . test.sh
  • 四、變量的使用
    • 4.1 變量定義與使用
    • 4.2 避免變量混淆
    • 4.3 位置變量
      • for循環和位置變量的結合案例
    • 4.4 read
  • 五、流程控制
    • 5.1 條件判斷:if-else結構
      • 5.1.1 基本語法
      • 5.1.2 條件測試
    • 5.2 case多分支
    • 5.3 for循環
    • 5.4 while循環
      • while 死循環
      • 算術表達式錯誤
        • 1. 賦值為字符串
        • 2. 使用正則表達式
  • 六、命令替換
  • 七、 函數
    • 1. 函數定義與使用
    • 2. 函數嵌套和變量的作用域問題
  • 八、數組
  • 總結


一、什么是shell腳本?

腳本:script: 一般是編程語言的文件,里面有很多的命令
本質上是一個文件,用來實現某個或者某些功能–》就是一個程序

輸入linux命令 --》shell --》解釋命令、查找命令、運行命令
shell編程—》linux里的命令編程–》把很多命令存放到一個文件里,可以用來實現很多的功能,這個文件就叫shell腳本

#!/bin/bash --》聲明解釋器使用的是/bin/bash 默認

[root@localhost shell]# cat /etc/shells 查看linux系統支持哪些shell
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
[root@localhost shell]# echo $SHELL 查看默認的shell是哪個
/bin/bash ????????# binary 二進制
[root@localhost shell]# env
SHELL=/bin/bash

shell腳本的執行順序,從上而下,如果中間的某條命令執行出錯,后面的命令是否執行?

默認會執行,直到腳本的末尾

[root@localhost shell]# vim test.sh 
set -e	# 告訴shell解釋器,一旦某條命令執行出錯,立馬退出當前shell,停止執行后面的命令
#!/bin/bash
for  i  in  {1..10}
doif  id feng\$i  &>/dev/null;thenecho "feng\$i 已經存在"	elseuseradd  feng\$i && echo "新建 feng\$i 用戶成功"fi
done
echo  "新建10個用戶成功"
fjdkfjdkj
echo "ok"

二、為什么要學習shell腳本?

  • 自動化任務:減少重復性工作(如備份、部署、日志分析)。
  • 系統管理:批量處理文件、監控服務器狀態、配置環境。
  • 效率提升:快速驗證想法,避免手動輸入大量命令。
  • 兼容性:幾乎所有 Linux/Unix 系統都支持,無需額外安裝。
  • 輕量級:無需編譯,直接運行,適合快速開發。
  • 集成工具:可調用其他程序(如 Python、grep、awk),擴展功能。
  • 求職需求:運維、開發工程師必備技能,提升競爭力。

三、腳本執行的方式

在當前終端里產生一個子bash進程去執行test.sh

[root@hz shell]# vim test.sh
#!/bin/bash
?
echo “$bigcity $num1”
?
i=1
echo $i
echo “end”
[root@hz shell]# bigcity=“shanghai”
[root@hz shell]# num1=3000
[root@hz shell]# ll test.sh
-rw-r–r–. 1 root root 59 6月 26 20:17 test.sh

3.1 bash test.sh

[root@hz shell]# bash test.sh
?
1
end
?
[root@hz shell]# export bigcity num1 # 輸出變量為全局變量
[root@hz shell]# bash test.sh
shanghai 3000
1
end


3.2 ./test.sh

必須提前授予可執行權限 chmod +x test.sh

[root@hz shell]# ./test.sh
-bash: ./test.sh: 權限不夠
?
[root@hz shell]# chmod +x test.sh
[root@hz shell]# ll test.sh
-rwxr-xr-x. 1 root root 59 6月 26 20:17 test.sh
[root@hz shell]# ./test.sh
?
1
end


3.3 source test.sh

在當前終端里(bash)去執行test.sh

[root@hz shell]# source test.sh
shanghai 3000
1
end


3.4 . test.sh

在當前終端里(bash)去執行test.sh

[root@hz shell]# . test.sh
shanghai 3000
1
end


四、變量的使用

4.1 變量定義與使用

[root@localhost feng]city=changsha
[root@localhost feng]echo $city
changsha
# shell編程,變量不定義可以直接使用
[root@localhost feng]# echo $CITY
?
[root@localhost feng]#

如果變量不定義,默認的值就是空值


4.2 避免變量混淆

可以使用{}單獨標識一個變量,這樣shell在解析命令的時候,就知道是一個單獨的變量了,不會和其他的字符拼接成一個新的變量

[root@hz shell]# filename=“sc”
[root@hz shell]# touch $filename{1. .10}.txt
[root@hz shell]# ls
?
[root@hz shell]# echo $filename{1. .10}.txt
.txt .txt .txt .txt .txt .txt .txt .txt .txt .txt
[root@hz shell]# echo $filename1
?
[root@hz shell]# echo $filename
sc
[root@hz shell]# echo $(filename)1
-bash: filename:未找到命令
1
[root@hz shell]# echo ${filename}1
sc1
[root@hz shell]# echo $filename-1
sc-1
[root@hz shell]# echo $filename_1
?
[root@hz shell]# echo ${filename}_1
sc_1


4.3 位置變量

傳參 position variable

[root@hz shell]# vim position_var.sh
#!bin/bsah
echo “第1個位置變量是:$1”
echo “第2個位置變量是:$2”
echo “第3個位置變量是:$3”
echo “第4個位置變量是:$4”
echo “腳本名字是:$0”
?
echo “一共有$#個位置變量”
echo “所有的位置變量:$@”
echo “所有的位置變量$*”
?
useradd $1
useradd $2
?
[root@hz shell]# bash position_var.sh shengyuran pengyaqin zhenglu caojie luobiao
第1個位置變量是:shengyuran
第2個位置變量是:pengyaqin
第3個位置變量是:zhenglu
第4個位置變量是:caojie
腳本名字是:position_var.sh
一共有5個位置變量
所有的位置變量:shengyuran pengyaqin zhenglu caojie luobiao
所有的位置變量shengyuran pengyaqin zhenglu caojie luobiao
?
[root@hz shell]# id shengyuran
用戶id=1026(shengyuran) 組id=1026(shengyuran) 組=1026(shengyuran)
[root@hz shell]# id pengyaqin
用戶id=1027(pengyaqin) 組id=1027(pengyaqin) 組=1027(pengyaqin)
[root@hz shell]# id caoajie
id: “caoajie”:無此用戶


for循環和位置變量的結合案例

[root@hz shell]# vim for.sh 
#!/bin/bash
for username in $@
douseradd $username
done
echo "for循環執行完畢"# 批量創建用戶,使用位置變量進行傳參
[root@hz shell]# bash for.sh caojie luobiao zouqiang zhenglu shengyuran pengyaqin
useradd:用戶“zhenglu”已存在
useradd:用戶“shengyuran”已存在
useradd:用戶“pengyaqin”已存在
for循環執行完畢

改進

[root@hz shell]# vim for.sh 
#!/bin/bash
for username in $@
doif id $username &>/dev/null;thenecho "\$username 用戶已經存在"echo "123456"|passwd \$username --stdinelseecho "$username 用戶不存在,立馬進行新建操作"useradd $username && echo "123456"|passwd $username --stdinfi
done
echo "for循環執行完畢"[root@hz shell]# bash for.sh shengyuran caojie panmingqian rose jack
shengyuran 用戶已經存在
更改用戶 shengyuran 的密碼 。
passwd:所有的身份驗證令牌已經成功更新。
caojie 用戶已經存在
更改用戶 caojie 的密碼 。
passwd:所有的身份驗證令牌已經成功更新。
panmingqian 用戶已經存在
更改用戶 panmingqian 的密碼 。
passwd:所有的身份驗證令牌已經成功更新。
rose 用戶不存在,立馬進行新建操作
更改用戶 rose 的密碼 。
passwd:所有的身份驗證令牌已經成功更新。
jack 用戶不存在,立馬進行新建操作
更改用戶 jack 的密碼 。
passwd:所有的身份驗證令牌已經成功更新。
for循環執行完畢

生成隨機密碼

[root@hz shell]# echo $RANDOM|sha256sum|cut -c1-10 ??# -c 截取字符串 character
a478bbad4f
[root@hz shell]# echo $RANDOM|md5sum|cut -c1-10
2d636621c5

for循環批量創建用戶并生成隨機密碼

[root@hz shell]# cat create_user.sh 
#!/bin/bash
for username in "$@"
doif id $username &>/dev/null;then# 產生隨機密碼u_passwd=$(echo RANDOM|sha256sum|cut -c1-10)echo "$username:$u_passwd"|chpasswd# 保存用戶名和密碼到文件里echo "username:$username password:$u_passwd" >>user_password.txtelse# 產生隨機密碼u_passwd=$(pwgen -s -y 10 1)echo "$username:$u_passwd"|chpasswd# 保存用戶名和密碼到文件里echo "username:$username password:$u_passwd" >>user_password.txtfi
done[root@hz shell]# bash create_user.sh  caojie luobiao hubiwu tom
chpasswd:第 1 行:用戶“hubiwu”不存在
chpasswd:發現錯誤,忽略改動
chpasswd:第 1 行:用戶“tom”不存在
chpasswd:發現錯誤,忽略改動[root@hz shell]# cat user_password.txt 
username:caojie password:7300a197d7
username:luobiao password:7300a197d7
username:hubiwu password:_,MpB$3]&\
username:tom password:-:B#BZ6v-`

4.4 read

適合交互式
將用戶輸入的內容賦值變量

[root@hz shell]# read -p “請輸入你的用戶名:” username promt 提示
請輸入你的用戶名:li
[root@hz shell]# echo $username
li
[root@hz shell]# read num1 num2 num3
10 20 30
[root@hz shell]# echo $num1 $num2 $num3
10 20 30

read設置用戶和密碼

[root@hz shell]# vim read.sh 
#!/bin/bash
read -p "請輸入用戶名:" username
read -p "請輸入你的密碼:" u_passwduseradd $username
echo $u_passwd|passwd $username --stdinecho "#####################"
read -p "請輸入你的選擇:" choice# || 表示前面的條件或后面的條件只要滿足一個就可以了,邏輯或	or
if [[ $choice == "y" || $choice == "Y" ]];thenecho "你的選擇是執行 yes"
elseecho "你的選擇是不執行 no"
fi[root@hz shell]# bash read.sh 
請輸入用戶名:j
請輸入你的密碼:123456
更改用戶 j 的密碼 。
passwd:所有的身份驗證令牌已經成功更新。
#####################
請輸入你的選擇:y
你的選擇是執行 yes

五、流程控制

5.1 條件判斷:if-else結構

對某種情況進行判斷 如果

5.1.1 基本語法

單分支:只有一種情況
雙分支:2種情況 else
if 命令1;then
????命令2
else
????命令3
fi
多分支:多種情況

字符串的判斷:使用雙中括號 --》支持字符串里有空格

[root@hz shell]# sg=“admin”
[root@hz shell]# [[ $sg == “feng” ]]
[root@hz shell]# echo $?
1
[root@hz shell]# [[ $sg == “admin” ]]
[root@hz shell]# echo $?
0
[root@hz ~]# sg=“ad min”
[root@hz ~]# [ $sg == “admin” ]
-bash: [: 參數太多
[root@hz ~]# sg=“admin”
[root@hz ~]# [ $sg == “admin” ]
[root@hz ~]# echo $?
0

; 命令連接符號
command1 ; command2 先執行第1個命令,然后去執行第2個命令 ,無論第一個命令執行是否成功,都會執行第二個命令

# 對if進行說明,if會自動去拿命令執行后的返回值
if[[ $? == 0 ]];thencommand
fiif[[ $? == 0 ]]
thencommand
fi

if-else 示例

[root@hz ~]# vim test.sh
#!/bin/bashmkdir -p /zou99
cd /zou99
touch zou{1..10}.txt
sg="zou123"
mkdir $sg
cd $sg
ls
# 對if進行說明,if會自動去拿命令執行后的返回值
if [[ $? != 0 ]];thenecho"上一條命令執行失敗"exit	# 退出
elseecho"繼續執行下面的命令"
fiecho "###############"
pwd
cp /etc/hosts .
mv hosts z_hosts
touch sc.txt sc1.txt
rm -rf sc.txt
echo "腳本執行完成"[root@hz ~]# bash test.sh
sc1.txt  z_hosts
繼續執行下面的命令
###############
/zou99/zou123
腳本執行完成

5.1.2 條件測試

  1. 文件測試

[ -e file ] 判斷文件是否存在 exist
[ -d file ] 判斷文件是否存在且是否為目錄 directory
[ -f file ] 判斷文件是否存在且是否為文件 file
[ -w file ] 判斷文件是否存在且是否為可寫文件 write
[ -x file ] 判斷文件是否存在且是否為可執行文件 execute
[ -r file ] 判斷文件是否存在且是否為可讀文件 read
[ -s file ] 判斷文件是否存在且是否為非空文件 size

[]test 功能一樣,如 test -e /etc/passwd

  1. 數值比較

推薦使用雙圓括號

[ int1 -gt int2 ] ((int1>int2)) greater than 大于
[ int1 -ge int2 ] ((int1>=int2)) greater equal 大于等于
[ int1 -eq int2 ] (( int1=int2 )) equal 等于
[ int1 -ne int2 ] (( int1!=int2 )) not equal 不等于
[ int1 -le int2 ] (( int1<=int2 )) less equal 少于等于
[ int1 -lt int2 ] (( int1<int2 )) less than 少于

小數比較用bc

[root@rocky ~]# echo “4.8 > 3”|bc
1
[root@rocky ~]# echo “4.8 > 5”|bc
0

  1. 字符串比較

[ "$a" = "$b" ] 相等
[ "$a" != "$b" ] 不相等
[ -n "$a" ][ "$a" ] 一樣 判斷字符串$a長度是否大于0
[ -z $a ] 判斷$a 的長度是否為0
[[ "$a" == *"redhat"* ]] 判斷在$a中是否含有redhat字符串

  1. 邏輯組合

&&(與) 、||(或)、!(非)

命令1 && 命令2 --》如果命令1執行成功,就執行命令2
命令1 || 命令2 --》如果命令1執行不成功,就執行命令2
命令1 && 命令2 || 命令3 --》如果命令1執行成功,就執行命令2,不成功執行命令3

[root@hz shell]# fjdk && echo “ok”
-bash: fjdk:未找到命令
[root@hz shell]# fjdk || echo “ok”
-bash: fjdk:未找到命令
ok
[root@hz shell]# fjdk && echo “ok” || echo “no”
-bash: fjdk:未找到命令
no

示例

[root@hz shell]vim create _file.sh
#!/bin/bash# 定義變量filename
filename="feng"mkdir -p /backup
cd /backup
touch ${filename}{1..100}.txt
mkdir -p   hunan beijing shanghai[ -d hunan ] && echo "hunan文件夾已經存在,新建成功"
[ -d beijing ] && echo "beijing文件夾已經存在,新建成功"
[ -d shanghai ] && echo "shanghai文件夾已經存在,新建成功"rm -rf feng??.txt
# 建一個文件包含當前日期,日期精確到秒
touch sc$(date +%Y%m%d%H%M%S)-{1..10}.txtif useradd zheng;thenecho "123456"|passwd zheng --stdin
elseexit 9	# 設置返回值為9
fiecho "腳本執行完畢"[root@hz shell]# bash create_file.sh 
hunan文件夾已經存在,新建成功
beijing文件夾已經存在,新建成功
shanghai文件夾已經存在,新建成功
更改用戶 zheng 的密碼 。
passwd:所有的身份驗證令牌已經成功更新。
腳本執行完畢
[root@hz shell]# echo $?
9
[root@hz shell]# ls /backup		# 驗證
beijing      feng3.txt  feng7.txt  sch20250706173336-10.txt  sch20250706173336-4.txt  sch20250706173336-8.txt
feng100.txt  feng4.txt  feng8.txt  sch20250706173336-1.txt   sch20250706173336-5.txt  sch20250706173336-9.txt
feng1.txt    feng5.txt  feng9.txt  sch20250706173336-2.txt   sch20250706173336-6.txt  shanghai
feng2.txt    feng6.txt  hunan      sch20250706173336-3.txt   sch20250706173336-7.txt

5.2 case多分支

case 變量 in
模式1)
?? 命令1
?? ;; # 終止一個模式分支
模式2|模式3) # 多個模式用豎線分隔
?? 命令2
?? ;;
*) # 默認分支
?? 默認命令
?? ;;
esac

[root@hz shell]# vim case.sh
#!/bin/bash
case $1 in
start)echo "開始執行相關操作"mkdir case_start;;
stop)echo "開始停止操作"mkdir case_stop;;
restart|reload|reboot)echo "開始重啟操作"mkdir case_restart;;
*)	echo "用法 $0 start|stop|restart|reload|reboot";;
esac

[root@hz shell]# bash case.sh start
開始執行相關操作
[root@hz shell]# bash case.sh stop
開始停止操作
[root@hz shell]# bash case.sh reload
開始重啟操作
[root@hz shell]# ls
case_restart case.sh case_start case_stop
[root@hz shell]# bash case.sh 1
用法 case.sh start|stop|restart|reload|reboot

if的多分支實現

[root@hz shell]# vim if3.sh
#!/bin/bash
if [[ $1 == "start" || $1 == "START" ]];thenecho "starting" && mkdir starting
elif[[ $1 == "stop" || $1 == "STOP" ]];thenecho "stoping" && mkdir stoping
elif[[ $1 == "restart" || $1 == "RESTART" ]];thenecho "restart"
elseecho "usage: $0 start|stop|restart"
fi[root@hz shell]# bash if3.sh restart
restart

5.3 for循環

for 變量 in 集合
do
???? 命令
done

[root@hz shell]# vim for.sh
#!/bin/bash
for i in {1..5}
doecho $i
done[root@hz shell]# bash for.sh 
1
2
3
4
5

5.4 while循環

while 條件(可以是執行一條命令)
do
????命令
done

[root@hz shell]# vim while.sh
i=1
while (( $i < 10 ))	# 雙圓括號:進行整數數值的比較和運算
do((i++))echo "$i "sleep 3	   # 讓當前進程暫停執行 3 秒
done

while 死循環

while true
while :

[root@hz shell]# vim while.sh
#!/bin/bash
i=1
while true
do((i++))echo "$i"sleep 3
done#控制循環次數為10次
i=1
#while true
while :
do((i++))echo "$i "sleep 1if (( $i == 10));thenbreakfi
done

有一個成績文件grade.txt里面記錄了很多同學的成績,具體如下:

[root@hz shell]# vim grade.txt
id name sex chinese English math
1 cali m 80 70 60
2 rose f 90 98 97
3 tom f 70 60 60
4 jack m 99 99 68

編寫腳本select_grade.sh 查詢出語文成績大于85的人的名字,性別,English,math,chinese

[root@hz shell]# vim select_grade.sh
#!/bin/bash
#讓while循環去讀取grade.txt文件里的內容,在讀取文件的時候,是一行一行讀取的
while read id name sex chinese English math
doif (( $chinese > 85 ));thenecho "$name $sex $English $math $chinese"fi
done < grade.txt	# 讀取 grade.txt 文件[root@hz shell]# bash select_grade.sh 
select_grade.sh:行5: ((: chinese:表達式遞歸層次越界 (錯誤符號是 "chinese")
rose f 98 97 90
jack m 99 68 99

算術表達式錯誤

(( $chinese > 85 )) 中的 $chinese 為非數字,導致 Shell 無法將其解釋為有效的數值

1. 賦值為字符串

當 while 循環讀取首行時,變量 chinese 的值會被賦值為字符串 “chinese”。此時:
[[ $chinese == “chinese” ]] 條件成立,執行 continue 跳過后續處理,避免將標題行作為數據處理

[root@hz shell]# cat select_grade.sh 
#!/bin/bash
while read id name sex chinese English math
doif [[ $chinese == "chinese" ]];thencontinuefiif (( $chinese > 85 ));thenecho "username:$name sex:$sex English:$English math:$math chinese:$chinese"fi
done < grade.txt[root@hz shell]# bash select_grade.sh 
username:rose sex:f English:98 math:97 chinese:90
username:jack sex:m English:99 math:68 chinese:99

2. 使用正則表達式

用正則表達式檢查chinese變量是否包含任意字母
先排除非數字的干擾行(如標題),再對有效數據進行條件篩選

[root@hz shell]# echo “fjgh”|grep “[a-Z]”
fjgh
[root@hz shell]# echo $?
0
[root@hz shell]# echo “123456”|grep “[a-Z]”
[root@hz shell]# echo $?
1

[a-z] 代表小寫a到Z
[A-Z] 代表大寫A到Z
[a-Z] 代表所有的小寫a到z和大寫的A到Z
[0-9] 代表0到9的數字

[root@hz shell]# cat select_grade_2.sh 
#!/bin/bashwhile read id name sex chinese English math
doif echo $chinese |grep "[a-Z]" &>/dev/null;thencontinuefiif (( $chinese > 85 ));thenecho "username:$name sex:$sex English:$English math:$math chinese:$chinese"fi
done < grade.txt[root@hz shell]# bash select_grade_2.sh 
username:rose sex:f English:98 math:97 chinese:90
username:jack sex:m English:99 math:68 chinese:99

read后面接的變量的個數盡量和grade.txt文件里的字段數(列)一樣,如果不一致,最后一個變量會包含后面字段的內容

[root@hz shell]# cat select_grade_3.sh 
#!/bin/bash
while read id name sex chinese
do	echo "username:$name sex:$sex English:$English math:$math chinese:$chinese"
done < grade.txt[root@hz shell]# bash select_grade_3.sh 
username:name sex:sex English: math: chinese:chinese	English	math
username:cali sex:m English: math: chinese:80		70		60
username:rose sex:f English: math: chinese:90		98		97
username:tom sex:f English: math: chinese:70		60		60
username:jack sex:m English: math: chinese:99		99		68

六、命令替換

優先執行命令,然后將命令執行結果賦值給變量

  1. varname=$(命令) --》推薦
  2. 反引號 varname=`命令`

單引號和雙引號
單引號 : 任何字符串都只是字符串本身,沒有特殊作用 --》所見即所得
雙引號: 里面的特殊符號,例如 $ 表示引用變量的值

[root@localhost feng]# city=changsha
[root@localhost feng]# echo “hello,$city”
hello,changsha
[root@localhost feng]# echo ‘hello,$city’
hello,$city
[root@localhost feng]# bigcity=`echo “hello,$city”`
[root@localhost feng]# echo $bigcity
hello,changsha
[root@localhost feng]# bigcity2=$(echo “hello,$city”)
[root@localhost feng]# echo $bigcity2
hello,changsha


七、 函數

function 一個功能用一個函數來實現
模塊化 --》復用

1. 函數定義與使用

編寫簡單的加法函數

[root@hz shell]#  vim f1.sh
#!/bin/bash
add() {total=$(( $1 + $2 ))echo "total is $ total"return 0
}add 50 60[root@hz shell]# bash f1.sh
total is 110
[root@hz shell]# echo $?
0

整個腳本的返回值取決于最后一條命令執行的返回值

return是退出函數的時候,給的返回值
exit是退出整個腳本的時候,給的返回值

[root@hz shell]# vim f1.sh
#!/bin/bash
add() {total=$(( $1 + $2 ))echo "total is $total"return 10
}add 50 60
echo "ok"
exit 99
echo "1"[root@hz shell]# bash f1.sh 
total is 110
ok
[root@hz shell]# echo $?
99

結合位置變量

[root@hz shell]# cat f2.sh
#!/bin/bash
num1=$1
num2=$2
add() {total=$(( $num1 + $num2 ))echo "total is $total"return 0
}add[root@hz shell]# bash f2.sh 50 60
total is 110

2. 函數嵌套和變量的作用域問題

函數自己也可以調用自己 --》循環的效果

A函數里的變量i,B函數也可以引用的,默認函數里的變量是全局變量,其他函數可以使用,所以注意變量名不要重復

整個腳本文件作為一個函數庫文件,里面包含了很多的函數,其他的腳本文件直接導入就可以使用里面的函數

local 聲明局部變量,限制變量的作用域僅在當前函數或代碼塊內,避免污染全局環境

全局變量和局部變量示例

# 定義加減法函數并展示結果
# total1和total2未使用local聲明,成為全局變量
[root@hz shell]# vim f2.sh
#!/bin/bash
num1=$1
num2=$2
add() {total1=$(( $num1 + $num2 ))echo "sum total is $total1"return 10
}
sub() {total2=$(( $num1 - $num2 ))echo "sub total is $total2"return 11
}
sc(){echo "求和: $total1 減法: $total2"
}add
sub
sc[root@hz shell]# bash f2.sh 99 88
sum total is 187
sub total is 11
求和: 187 減法: 11# 在 add() 和 sub() 中,total1 和 total2 被聲明為 局部變量,
# 其作用域僅限于函數內部,因此 sc() 輸出的是未定義的變量(空值)
[root@hz shell]# vim f2.sh
#!/bin/bash
num1=$1
num2=$2
add() {local total1=$(( $num1 + $num2 ))echo "sum total is $total1"return 10
}
sub() {local total2=$(( $num1 - $num2 ))echo "sub total is $total2"return 11
}
sc(){echo "求和: $total1 減法: $total2"
}add
sub
sc[root@hz shell]# bash f2.sh 99 88
sum total is 187
sub total is 11
求和:  減法: 

即使通過 source 導入腳本,其他函數(如 sc())仍然無法直接訪問這些局部變量
當 add() 和 sub() 執行結束后,其局部變量會被銷毀
sc() 調用時,total1 和 total2 已不存在,因此顯示為空

[root@hz shell]# vim f3.sh
#!/bin/bash
num1=$1
num2=$2
add() {local total1=$(( $num1 + $num2 ))echo "sum total is $total1"return 10
}
sub() {local total2=$(( $num1 - $num2 ))echo "sub total is $total2"return 11
}
sc(){echo "求和: $total1 減法: $total2"
}[root@hz shell]# vim f4.sh
#!/bin/bash# 導入f3.sh腳本文件,獲取里面的函數
source f3.sh
# .f3.shmul() {echo "乘法結果: $((num1 * num2)) "
}
add
sub
sc
mul[root@hz shell]# bash f4.sh 90 80
sum total is 170
sub total is 10
求和:  減法: 
乘法結果: 7200 

八、數組

是一個集合,里面有很多的東西(數字,字符串)
元素:是一個數組里的一個內容
下標(索引):是數組里的內容的編號

數組的定義
使用括號 () 包裹元素,元素間用空格分隔

singers=(“zouqiang” “caojie” “zhoujielun” “rose”)
???????????????????? 0 ????????????? 1 ??????????? 2 ???????????? 3

[root@rocky ~]# singers=(“zouqiang” “caojie” “zhoujielun” “rose”)
# 通過下標訪問元素
[root@rocky ~]# echo ${singers[0]}
zouqiang
# 訪問所有元素
[root@rocky shell]# echo ${singers[@]}
zouqiang caojie zhoujielun rose
# 獲取數組元素個數
[root@rocky ~]# echo ${#singers[@]}
4
# 獲取所有下標
[root@rocky ~]# echo ${!singers[@]}
0 1 2 3
# 刪除一個元素,會導致下標不連續
[root@rocky ~]# unset singers[2]
[root@rocky ~]# echo ${!singers[@]}
0 1 3
[root@rocky ~]# echo ${#singers[@]}
3
# 從命令輸出創建數組
[root@rocky ~]# name=($(cat /etc/passwd|awk -F: ‘{print $1}’))
[root@rocky ~]# echo ${name[@]}
root bin daemon adm lp sync shutdown halt mail operator games


編寫一個點歌程序sing.sh 從歌手名單singers.txt里隨機抽取歌手,當所有的歌手都抽取完后,重新開始

歌手文件

[root@rocky shell]# cat singers.txt
tom
jerry
rose
jack
feng
li
zhang

腳本文件

>[root@rocky shell]# cat sing.sh
#!/bin/bash
singers=($(cat singers.txt))
# 隨機抽取歌手
while true
doif (( ${#singers[@]} == 0 ));thenecho "所有的歌手都抽取完畢,需要重新開始"exit	filucky_num=$(( RANDOM % ${#singers[@]}))echo "請著名歌手 ${singers[$lucky_num]}"unset singers[$lucky_num]singers=($(echo ${singers[@]}))read -p "請輸入任意鍵繼續"
done

執行效果

[root@rocky shell]# bash sing.sh
請著名歌手 jerry
請輸入任意鍵繼續
請著名歌手 li
請輸入任意鍵繼續
請著名歌手 feng
請輸入任意鍵繼續
請著名歌手 tom
請輸入任意鍵繼續
請著名歌手 jack
請輸入任意鍵繼續
請著名歌手 zhang
請輸入任意鍵繼續
請著名歌手 rose
請輸入任意鍵繼續
所有的歌手都抽取完畢,需要重新開始

用文件來存放已經抽取過的名單

[root@rocky shell]# cat sing2.sh 
#!/bin/bash
# 新建一個存放已經唱過歌的歌手的名單文件
>pass.txt
i=1
while :
do	pass_lines=$(cat pass.txt|wc -l)total_lines=$(cat singers.txt|wc -l)# 判斷pass.txt和singers.txt文件的行數是否一樣,來判斷歌手是否全部唱完if (( $pass_lines == $total_lines ));thenecho "全部歌手已經唱完,重新開始"exitfi# 隨機抽取一個歌手對應的行數lucky_num=$(( $RANDOM % $total_lines  + 1))# 歌手的名字singer_name=$(cat singers.txt |head -n $lucky_num |tail -1)if  grep $singer_name pass.txt &>/dev/null ;thencontinueelseecho "$i 請著名歌手 $singer_name 演唱歌曲"|tee -a pass.txtfisleep 1((i++))
done

[root@rocky shell]# bash sing2.sh
1 請著名歌手 zhang 演唱歌曲
2 請著名歌手 feng 演唱歌曲
3 請著名歌手 jerry 演唱歌曲
4 請著名歌手 tom 演唱歌曲
5 請著名歌手 jack 演唱歌曲
6 請著名歌手 rose 演唱歌曲
7 請著名歌手 li 演唱歌曲
全部歌手已經唱完,重新開始


總結

Shell 腳本的價值在于將人力從重復勞動中解放出來,通過代碼實現:

  • 效率提升:減少手動操作,縮短任務執行時間
  • 一致性:避免人工誤差,確保每次執行結果相同
  • 可維護性:將操作步驟文檔化,便于團隊協作和知識傳承
  • 擴展性:可與其他工具無縫集成,構建復雜的自動化系統

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

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

相關文章

【嵌入式】51單片機學習筆記-Keil5軟件安裝教程

00. 目錄 文章目錄00. 目錄01. Keil C51概述02. Keil C51下載03. Keil C51安裝04. Keil C51注冊05. 附錄01. Keil C51概述 Keil C51 是德國Keil公司&#xff08;現被ARM收購&#xff09;開發的嵌入式開發工具&#xff0c;專注于8051單片機的C語言和匯編開發。它是μVision IDE…

ai之 ubuntu本地安裝mineru2.1.0

MinerU 目錄 一、更新內容概述寫在前面的話:總體來看,2.0版本升級為全新的 VLM 解析模式,更優于以前的基礎解析方式。二、MinerU 安裝部署下面使用源碼來進行環境安裝。注意:當前狀態說明推薦解決方案如果是下載插件慢可以 指定阿里源三、MinerU 使用1. 在線體驗2. 命令行使…

華為昇騰NPU與NVIDIA CUDA生態兼容層開發實錄:手寫算子自動轉換工具鏈(AST級代碼遷移方案)

點擊 “AladdinEdu&#xff0c;同學們用得起的【H卡】算力平臺”&#xff0c;H卡級別算力&#xff0c;按量計費&#xff0c;靈活彈性&#xff0c;頂級配置&#xff0c;學生專屬優惠。 當國產AI芯片崛起遭遇生態壁壘&#xff0c;如何實現CUDA算子到昇騰平臺的無損遷移成為關鍵挑…

GraphRAG Docker化部署,接入本地Ollama完整技術指南:從零基礎到生產部署的系統性知識體系

相關推薦&#xff1a;Umi-OCR 的 Docker安裝&#xff08;win制作鏡像&#xff0c;Linux&#xff08;Ubuntu Server 22.04&#xff09;離線部署&#xff09; 一、技術背景與發展脈絡 1.1 RAG技術演進歷程分析 檢索增強生成&#xff08;RAG&#xff09;技術的發展經歷了三個重要…

Android 系統默認Launcher3 菜單模式雙層改成單層-3

Android 系統默認自帶Launcher3 菜單都為雙層模式 各手機大廠的Launcher的菜單模式都為單層 如何將launcher3的菜單模式改為單層模式 mOverviewPanel = (ViewGroup) findViewById(R.id.overview_panel); mWidgetsButton = findViewById(R.id.widget_butto…

基于k8s環境下pulsar高可用測試和擴縮容(上)

#作者&#xff1a;任少近 文章目錄Pulsar高可用測試1. 測試目的2.當前集群環境說明3. 模擬故障場景4.功能驗證5.結論Pulsar高可用測試 1. 測試目的 本次測試旨在驗證 Apache Pulsar 在某個 Broker 節點宕機&#xff08;down&#xff09;的情況下&#xff0c;是否仍能正常提供…

JAVA JVM垃圾收集

JVM 垃圾收集是 Java 自動內存管理的核心&#xff0c;本文通過圍繞 “哪些是垃圾、何時回收、怎么回收、用啥回收器、內存咋分配” 等展開一、判斷哪些是垃圾引用計數法&#xff1a;給對象分配引用計數器&#xff0c;有引用時計數加 1&#xff0c;引用失效減 1 &#xff0c;計數…

UniHttp生命周期鉤子與公共參數實戰:打造智能天氣接口客戶端

> 通過靈活的生命周期鉤子,我們讓HTTP請求從機械操作進化為智能對話 在現代應用開發中,高效處理HTTP請求是核心能力。本文將深入探索UniHttp框架中強大的**HttpApiProcessor生命周期鉤子**,并演示如何利用其**公共參數填充機制**優雅地處理第三方接口。我們將以百度天…

C++高級編程,類模版成員函數類外實現

#include <iostream> #include <string>//類模版成員函數類外實現 template<class T1,class T2> class Person {//Person構造函數 public:Person(T1 name,T2 age);// {// this->m_Namename;// this->m_Ageage;// }//Person的成員函數void show…

[Linux入門 ] RAID存儲技術概述

一.數據存儲架構 1??存儲系統 2??主機系統 3??互連部件 4??存儲設備與磁盤陣列 二.數據存儲技術 1??數據冗余技術 2??RAID 0 3??RAID 1 4??RAID 2 5??RAID 3 6??RAID 4 三.基于硬件的RAID磁盤陣列 1??陣列卡(RAID控制器) 2??陣列卡種類 …

AI繪畫生成章邯全身像提示詞

融合了歷史元素和視覺表現力&#xff0c;力求生成符合秦末名將章邯身份的全身像。 核心提示詞結構&#xff1a; [主體描述]&#xff0c;[服裝/盔甲細節]&#xff0c;[姿態/神情]&#xff0c;[武器]&#xff0c;[背景/氛圍]&#xff0c;[風格/質量]&#xff0c;[參數] 選項一&…

iOS高級開發工程師面試——關于優化

iOS高級開發工程師面試——關于優化 一、TableView 有什么好的性能優化方案?二、界面卡頓和檢測你都是怎么處理?三、談談你對離屏渲染的理解?四、如何降低APP包的大小?五、日常如何檢查內存泄露?六、APP啟動時間應從哪些方面優化?一、TableView 有什么好的性能優化方案?…

線性基學習筆記

我們稱一個線性空間 V V V 的一個極大線性無關集為這個線性空間的線性基,簡稱基。 異或線性基 在異或空間下,我們定義如下內容。 異或和 設 S S

ESP-Timer入門(基于ESP-IDF-5.4)

主要參考資料&#xff1a; ESP 定時器&#xff08;高分辨率定時器&#xff09;: https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32s3/api-reference/system/esp_timer.html 目錄ESP-Timer與FreeRTOS TimerAPI 使用1.創建定時器2.啟動定時器3.管理定時器4.時間管…

014_批處理與大規模任務

批處理與大規模任務 目錄 批處理概述核心優勢技術規格API使用管理和監控應用場景最佳實踐 批處理概述 什么是批處理 批處理&#xff08;Batch Processing&#xff09;是一種異步處理大量Claude API請求的方法&#xff0c;允許您一次性提交多個消息請求&#xff0c;系統將在…

Python淘寶拍立淘按圖搜索API接口,json數據示例參考

淘寶拍立淘按圖搜索API接口示例淘寶的拍立淘(圖片搜索)功能通常是通過淘寶開放平臺提供的API實現的。以下是一個模擬的JSON數據示例和接口調用參考&#xff1a;模擬API請求示例import requestsimport base64# 示例圖片路徑image_path "example.jpg"# 讀取圖片并編碼…

靜默的田野革命—人工智能重構農業生態的技術風暴與文明悖論

一、饑餓困局的數字突圍當全球糧食損失率高達30%&#xff08;約13億噸&#xff09;與8億人營養不良并存&#xff0c;當農藥濫用導致傳粉昆蟲種群崩潰與地下水資源枯竭&#xff0c;傳統農業的生態死結日益收緊。這場危機的核心是生物復雜性對工業化農業的報復&#xff1a;小麥基…

【大模型推理論文閱讀】 Thinking Tokens are Information Peaks in LLM Reasoning

Demystifying Reasoning Dynamics with Mutual Information&#xff1a;Thinking Tokens are Information Peaks in LLM Reasoning 摘要 大語言推理模型&#xff08;LRM&#xff09;在復雜問題解決方面展現出了令人矚目的能力&#xff0c;但其內部推理機制仍未得到充分理解。…

【TCP/IP】14. 遠程登錄協議

14. 遠程登錄協議14. 遠程登錄協議14.1 基本概念14.2 Telnet 命令14.3 Telnet 選項及協商14.4 Telnet 子選項協商14.5 Telnet 操作模式本章要點14. 遠程登錄協議 14.1 基本概念 Telnet 協議是 TCP/IP 協議族的重要成員&#xff0c;核心功能是實現本地計算機對遠程主機的終端仿…

Flink1.20.1集成Paimon遇到的問題

flinkcdc mysql 到paimon 1&#xff1a;Caused by: java.lang.ClassNotFoundException: org.apache.kafka.connect.data.Schema 可以參考這個文章 明確指出了flink-connector-mysql-cdc-3.4.0.jar存在這個包&#xff0c;但是flink-sql-connector-mysql-cdc-3.4.0.jar中沒有這個…