Shell腳本的基礎知識學習

Shell 腳本是 Linux/Unix 系統的核心自動化工具,能夠完成以下任務:
(1)批量操作:一鍵安裝軟件、批量處理文件(重命名、壓縮、備份等)。
(2)系統管理:監控資源(CPU、內存、磁盤)、定時任務(cron)、日志分析。
(3)開發輔助:編譯自動化、環境配置、CI/CD 流水線集成。

適用讀者
(1)零基礎初學者,希望掌握 Linux 基礎操作。
(2)運維工程師,提升自動化運維能力。
(3)開發人員,優化本地開發環境和工作流程。

一、Shell基礎概念

1.1 什么是 Shell?

定義:
Shell 是用戶與操作系統內核(Kernel)之間的命令行接口,負責解析用戶輸入的命令并調用系統功能。

核心作用:
(1)執行命令和腳本
(2)管理進程和文件系統
(3)環境變量管理
(4)自動化任務處理

1.2 Shell 類型與選擇

# 查看系統支持的 Shell
cat /etc/shells
# 典型輸出:
# /bin/sh
# /bin/bash
# /usr/bin/zsh
# /bin/dash

常見 Shell 對比:

Shell 類型特點
BashLinux 默認 Shell,支持歷史命令、自動補全、數組等擴展功能
Zsh強大的交互式 Shell,支持主題和插件(如 Oh My Zsh)
Dash輕量高效,適合系統啟動腳本(Ubuntu 的 /bin/sh 默認指向 Dash)
Ksh兼容 POSIX 標準,適合商業環境

1.3 腳本執行方式

方式1:sh執行,指的是用腳本對應的sh或bash來接著腳本執行

bash script.sh

方式2: 工作目錄執行,指的是執行腳本時,先進入到腳本所在的目錄(此時,稱為工作目錄),然后使用 ./腳本方式執行

[root@localhost shell]# ./9*9.sh
-bash: ./1.sh: Permission denied
[root@localhost shell]# chmod +x 9*9.sh    //賦予權限  x代表執行權限
[root@localhost shell]# ./9*9.sh        //執行腳本

方式3:shell環境執行,指的是在當前的shell環境中執行,可以使用 . 接腳本 或 source 接腳本

source script.sh

方式4:絕對路徑執行,指的是直接從根目錄/到腳本目錄的絕對路徑

/root/script.sh

二、shell基礎命令

2.1 基礎命令

(1)查看腳本執行過程

[root@localhost shell]# bash -x 9*9.sh
++ seq 9
+ for i in '`seq 9`'
++ seq 1
+ for j in '`seq $i`'
+ printf '1*1=%2d ' 1
1*1= 1 + echo ''

(2)查看腳本是否有語法錯誤

[root@localhost shell]# bash -n 9*9.sh

2.2 Date命令

(1)顯示年月日

[root@localhost ~]# date +%Y-%m-%d
2024-10-08
[root@localhost ~]# date +%y-%m-%d
24-10-08
[root@localhost ~]# date +%F
2024-10-08

(2) 顯示時分秒

[root@localhost ~]# date +%T
15:04:36
[root@localhost ~]# date +%H:%M:%S
15:04:52

(3)顯示星期

[root@shell ~]# date +%w
5
[root@shell ~]# date +%W
41

(4)時間戳

使用命令date +%s 顯示從 1970 年 1 月 1 日 00:00:00 到目前為止的秒數。

[root@shell ~]# date +%s
1728608466

使用date -d@1728608466 顯示輸入描述前的時間

[root@shell ~]# date -d@1728608466
20241011日 星期五 09:01:06 CST

(5)顯示一個小時之前、后

date -d "+1 hour"    #一個小時后
date -d "-1 hour"    #一個小時前

(6)顯示一天之前、之后

date -d "+1day"     #一天后
date -d "-1 day"     #一天前

2.3 重定向及管道

前言:標準流

文件描述符名稱默認目標
0標準輸入鍵盤
1標準輸出屏幕
2標準錯誤屏幕

1.輸出重定向(>和>>)

1.1標準輸出重定向(>)

作用:將命令的標準輸出重定向到文件。如果文件不存在,則創建文件;如果文件存在,則覆蓋原有內容。

示例1:ls -l > file_list.txt,此命令會將ls -l(列出文件詳細信息)的輸出結果保存到file_list.txt文件中。如果file_list.txt之前有內容,會被覆蓋。

實例2:在script.sh腳本中,將echo命令的輸出重定向到一個文件。
在這里插入圖片描述

1.2標準輸出追加重定向(>>)

作用:將命令的標準輸出追加到文件末尾。如果文件不存在,則創建文件。

示例:echo “New line” >> log.txt,會將字符串 “New line” 添加到log.txt文件的末尾。

1.3標準錯誤重定向(2>)

作用:將命令執行過程中產生的標準錯誤輸出重定向到文件。

示例:grep non_existent_pattern file.txt 2> error.log,當grep命令在file.txt中找不到指定模式時,產生的錯誤信息會被保存到error.log文件中,而不是顯示在終端。

1.4標準錯誤追加重定向(2>>)

作用:將標準錯誤輸出追加到文件末尾。

示例:在一個循環執行可能出錯的命令腳本中,for i in $(seq 1 5); do command_that_might_fail 2>> error_accumulate.log; done,每次循環中命令產生的錯誤信息都會被追加到error_accumulate.log文件中。

1.5合并標準輸出和標準錯誤重定向(&> 或 >&)

作用:將命令的標準輸出和標準錯誤輸出同時重定向到一個文件。

示例:find. -name “*.bak” &> output_and_error.log,find命令的所有輸出(包括正常輸出和可能出現的錯誤輸出)都會被保存到output_and_error.log文件中。

2.輸入重定向(<)

用法:將文件的內容作為命令的輸入。

示例 1:
假設有一個input.txt文件,內容為一些數字 “1 2 3 4 5”,使用sort命令對這些數字進行排序,通過輸入重定向來讀取文件內容作為輸入。
在這里插入圖片描述
運行腳本后,會輸出排序后的數字 “1 2 3 4 5”。如果沒有輸入重定向,sort命令會等待用戶從鍵盤輸入內容進行排序。

示例 2:使用wc -l命令(用于統計行數)來統計text_file.txt文件的行數,通過輸入重定向。
在這里插入圖片描述

3. 管道和重定向結合(|和>或>>)

用法:管道(|)用于將一個命令的輸出作為另一個命令的輸入,再結合重定向可以進一步處理輸出結果。

1.保存管道中間結果并繼續處理:
示例:cat data.txt | grep “important” > intermediate_result.txt,這個命令先通過cat和grep組合從data.txt中篩選出包含 “important” 的行,然后將這些篩選后的結果保存到intermediate_result.txt文件中。之后可以對這個文件進行其他操作,如sort intermediate_result.txt。

2.實時處理并記錄結果:
示例:tail -f access.log | grep “404” > error_404.log,tail -f access.log會實時跟蹤access.log文件的新增內容,通過管道將這些內容傳遞給grep命令來查找包含 “404” 的行,然后將這些行保存到error_404.log文件中,用于實時監控網站的 404 錯誤。

3.復雜數據處理流程:
示例:find. -type f -name “*.txt” -exec cat {} ; | awk ‘{print $1}’ | sort | uniq -c > result.txt,這個命令首先使用find命令查找當前目錄下所有的.txt文件,并將這些文件的內容通過cat命令輸出,然后通過管道將這些內容傳遞給awk命令提取每行的第一個字段,接著進行排序和去重統計,最后將結果重定向到result.txt文件中,用于分析.txt文件內容的第一個字段的統計信息。

示例 1:
先使用cat命令讀取file.txt文件內容,然后通過管道將輸出傳遞給grep命令來查找包含特定單詞(如 “error”)的行,最后將結果覆蓋寫入到error_lines.txt文件。
在這里插入圖片描述

示例 2:
先使用ps -ef命令獲取所有進程信息,然后通過管道將輸出傳遞給grep命令查找包含特定進程名(如 “httpd”)的行,最后將結果追加到process_log.txt文件。
在這里插入圖片描述

三、變量與數據類型

3.1 變量操作

(1) 定義與賦值

name="John"         # 字符串(等號兩側不可有空格)
count=42            # 整型
files=$(ls)         # 命令替換賦值
readonly PI=3.14    # 只讀變量

(2) 變量引用與刪除

echo $name # 輸出變量值
echo ${name} # 推薦寫法(明確變量邊界)
unset name # 刪除變量

(3)與用戶交互

這里相當于把用戶交互時寫的值賦予給變量n

[root@shell ~]# read -p "請輸入一個數字:" n
請輸入一個數字:20
[root@shell ~]# echo $n
20

由于沒有創造一個變量接收值,系統默認變量REPLY

[root@shell ~]# read -p "請輸入一個數字:"
請輸入一個數字:30
[root@shell ~]# echo $REPLY
30

3.2 變量作用域

類型定義方式作用范圍生命周期
局部變量var=value當前 Shell 進程進程結束銷毀
環境變量export var=value當前進程及其子進程進程結束銷毀
永久變量寫入配置文件所有新啟動的 Shell系統重啟有效

環境變量配置文件:
(1)用戶級:~/.bashrc, ~/.bash_profile
(2)系統級:/etc/profile, /etc/environment
(3)以上配置文件定義變量不是實時生效,需要resource刷新一下

3.3 特殊變量

變量描述
$0當前腳本名稱
$1-$9腳本參數(第1到第9個)
${10}位置參數10
$#參數個數
$*所有參數(合并為一個字符串),整體作為單個字符串
$@所有參數(保留原始分隔符),每個作為單獨字符串
${#*}傳遞到腳本中的命令行參數的個數
$?返回值,用于判斷前一命令是否執行成功,0為成功,1則失敗
$$當前進程 PID
$-傳遞到腳本中的標識
$_之前命令的最后一個參數
$!運行在后臺的最后一個作業的進程ID(PID)

示例:

[root@localhost ~]# vi cbd.sh
#!/bin/bash
echo "$1"
echo "第二個參數是$2"
echo "第三個參數是$3"
echo "本腳本一共有$#個參數"
echo "所有位置參數(作為單個字符串)為:"$*""
echo "所有位置參數每個作為單獨字符串)為:"$@""
echo "$0"
echo "腳本中的命令行參數的個數為:${#*}"
echo "腳本中的標識為:$-"
echo "命令的最后一個參數為:$_"

在這里插入圖片描述
判斷上一命令是否執行成功

[root@shell ~]# echo $?
0

3.4 系統變量

變量描述示例值使用場景
$PATH可執行文件搜索路徑。命令所示路徑,以冒號為分割;/usr/bin:/usr/local/bin添加自定義命令路徑:export PATH=$PATH:/myapp
$HOME當前用戶主目錄/home/user快速訪問家目錄:cd $HOME
$USER當前用戶名john日志記錄:echo “User: $USER”
$PWD當前工作目錄/var/www獲取腳本所在目錄:cd $(dirname $0)
$SHELL當前使用的 Shell 路徑/bin/bash檢查 Shell 類型:echo $SHELL
$LANG系統語言設置en_US.UTF-8設置腳本輸出語言:export LANG=C
$RANDOM生成隨機數(0-32767)15872創建臨時密碼:passwd=$(echo $RANDOM
$SECONDS腳本已運行時間(秒)30計算執行耗時:echo “耗時: $SECONDS 秒”
$BASH_VERSIONBash 版本信息5.1.16(1)-release檢查 Bash 特性兼容性
[root@shell ~]# echo $SHELL                #顯示當前Shell類型;
/bin/bash
[root@shell ~]# echo $PATH                  #命令所示路徑,以冒號為分割;
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@shell ~]# echo $PWD                   #顯示當前所在路徑;
/root
[root@shell ~]# echo $RANDOM          #隨機生成一個 0 至 32767 的整數;
7532

四、運算符與運算

4.1 算術運算

a=10 b=3
# 方式1:$(( ))
echo $((a + b))      # 13
# 方式2:expr(需空格)+ , - , \*,  /,  %    加,減,乘,除,取余
expr $a + $b        # 13
# 方式3:let
let "c = a * b"
echo $c             # 30
# 方式4:bc(浮點運算)
echo "scale=2; 10/3" | bc  # 3.33
# 方式5:[]
echo $[a+b]

4.2 比較運算符

(1) 數值比較

運算符描述示例
-eq等于[ $a -eq 10 ]
-ne不等于[[ $a -ne 5 ]]
-gt大于[ $b -gt 2 ]
-lt小于[ $b -lt 2 ]
-ge大于等于[ $b -ge 2 ]
-le小于等于[ $b -le2 ]

(2) 字符串比較

str1="hello"
str2="world"
[ "$str1" = "hello" ]   # 等于
[[ "$str1" != "$str2" ]] # 不等于
[ -z "$str" ]           # 判斷空字符串

(3) 文件測試

[ -f "file.txt" ]    # 是普通文件
[ -d "/tmp" ]        # 是目錄
[ -x "/usr/bin/git" ] # 可執行

4.3 邏輯運算符

# 邏輯與(&&)
[ $a -gt 5 ] && [ $b -lt 10 ]
# 邏輯或(||)
[[ -f "file" ]] || echo "文件不存在"
# 邏輯非(!)
if ! [ -d "/tmp" ]; thenmkdir /tmp
fi

五、字符串和數組

5.1 Shell字符串

定義:
字符串可以由單引號’ '包圍,也可以由雙引號" "包圍,也可以不用引號。

三種形式的區別:

  1. 不被引號包圍的字符串:不被引號包圍的字符串中出現變量時也會被解析;字符串中不能出現空格,否則空格后邊的字符串會作為其他變量或者命令解析。

  2. 由單引號包圍的字符串:任何字符都會原樣輸出,在其中使用變量是無效的;字符串中不能出現單引號,對單引號進行轉義也不行。

  3. 由雙引號" "包圍的字符串: 如果其中包含了某個變量,那么該變量會被解析,得到該變量的值,而不是原樣輸出;字符串中可以出現雙引號。

a. 獲取字符串長度:

${#字符串名}

[root@shell ~]# rzc1="123456"
[root@shell ~]# echo ${#rzc1}
6

b.字符串拼接

將兩個字符串并排放在一起就能實現拼接。$str1 $str2這種寫法不允許變量之間有空格,但是只要加上””就可以

[root@localhost ~]# rzc2="8910jqk"
[root@localhost ~]# rzc3=$rzc1$rzc2
[root@localhost ~]# echo $rzc3
12345678910jqk

c. 字符串截取

shell截取字符串通常有兩種方式:從指定位置開始截取和從指定字符(子字符串)開始截取。
(1)從左邊開始計數時,起始數字是0(這符合程序員思維);從右邊開始計數時,起始數字是1(這符合常人思維)。計數方向不同,起始數字也不同。

(2)不管從哪邊開始計數,截取方向都是從左到右。且截取的原則為[ ),即左閉右開

使用指定位置從左邊開始截取:

[root@shell ~]# echo ${rzc1:2:2}       #2代表從左往右數第二個數   2代表輸出兩個數
34
[root@shell ~]# echo ${rzc1:1:2}      #1 從左往右數第一個數   2 輸出兩個數字
23
[root@shell ~]# echo ${rzc1:1:4}
2345

使用指定位置從右邊開始截取:

[root@shell ~]# echo ${rzc1:0-3:2}
45
[root@shell ~]# echo ${rzc1:0-4:2}
34

使用字符指定從左邊開始截取:

使用#號可以截取指定字符(或者子字符串)右邊的所有字符。

*是通配符的一種,表示任意長度的字符串。*字符3連起來使用的意思是:忽略左邊的所有字符,直到遇見字符3(3字符不會被截取)。

[root@shell ~]# echo ${rzc1#*3}
456

使用字符指定從右邊開始截取:
使用%號可以截取指定字符(或者子字符串)左邊的所有字符。
注意的位置,因為要截取字符3左邊的字符,而忽略3右邊的字符,所以應該位于3的右側。

[root@shell ~]# echo ${rzc1%3*}
12

5.2 字符串替換

格式:${字符串/要替換的字符/替換的字符}

[root@shell ~]# rzc4="welcome my word"
[root@shell ~]# echo $rzc4
welcome my word
[root@shell ~]# echo ${rzc4/my/you}
welcome you word
str="Hello World"
# 截取子串
echo ${str:0:5}      # Hello
# 替換操作
echo ${str/World/Shell}  # Hello Shell
# 分割字符串
IFS=' ' read -ra parts <<< "$str"
echo ${parts[1]}     # World

5.3 shell數組

概述:
bash支持一維數組(不支持多維數組),并且沒有限定數組的大小。數組是相同類型的元素按一定順序排列的集合。 類似與 C 語言,數組元素的索引由 0 開始編號。獲取數組中的元素要利用索引,索引可以是整數或算術表達式,其值應大于或等于 0。

定義:
在 Shell 中,用括號來表示數組,數組元素用“空格”符號分割開

格式:數組名=(元素1 元素2 元素3 元素n)

1. 獲取數組元素的值:

${數組名[索引]}

[root@localhost ~]# array1=(aa bb cc dd)
[root@localhost ~]# echo ${array1[0]}
aa
[root@localhost ~]# echo ${array1[1]}
bb
[root@localhost ~]#
# 定義數組
colors=("red" "green" "blue")
# 訪問元素
echo ${colors[1]}    # green
# 遍歷數組
for color in "${colors[@]}"; doecho $color
done
# 關聯數組(Bash 4+)
declare -A user=(["name"]="Alice" ["age"]=30)
echo ${user["name"]}  # Alice

2. 獲取數組長度

利用@或*,可以將數組擴展成列表,然后使用#來獲取數組元素的個數。

[root@localhost ~]# echo ${#array1[@]}
4
[root@localhost ~]# echo ${#array1[*]}
4

3. 數據拼接、合并

Shell數組拼接(數組合并),將兩個數組連接成一個數組。拼接數組的思路是:先利用@或*,將數組擴展成列表,然后再合并到一起。

[root@shell ~]# array1=(aa bb cc dd)
[root@shell ~]# echo ${array1[@]}
aa bb cc dd
[root@shell ~]# array2=(ee ff gg hh)
[root@shell ~]# echo ${array2[@]}
ee ff gg hh
[root@shell ~]# array3=(${array2[@]} ${array1[@]})
[root@shell ~]# echo ${array3[@]}
ee ff gg hh aa bb cc dd

4.數組的賦值

利用索引對指定元素進行賦值

[root@localhost ~]# echo ${array1[@]}aa bb cc dd
[root@localhost ~]# array1[1]=20 
[root@localhost ~]# echo ${array1[@]}aa 20 cc dd

5.數組的刪除

利用命令unset 對數組索引指定的元素進行刪除

[root@localhost ~]# echo ${array1[@]}aa 20 cc dd
[root@localhost ~]# unset array1[1]
[root@localhost ~]# echo ${array1[@]}
aa cc dd

6.數組切片

格式:${數組名[@]:索引開始:索引結束}

[root@shell ~]# echo ${array3[@]}
ee ff gg hh aa bb cc dd
[root@shell ~]# echo ${array3[@]:1:4}
ff gg hh aa

六、流程控制

6.1 If語句

腳本中常見的邏輯判斷運算符:

-f     判斷文件是否存在 eg: if [ -f filename ]-d     判斷目錄是否存在 eg: if [ -d dir     ]-eq    等于,應用于整型比較 equal;
-ne    不等于,應用于整型比較 not equal;
-lt    小于,應用于整型比較 letter;
-gt    大于,應用于整型比較 greater;
-le    小于或等于,應用于整型比較;
-ge    大于或等于,應用于整型比較;
-a     雙方都成立(and) 邏輯表達式 –a 邏輯表達式;
-o     單方成立(or) 邏輯表達式 –o 邏輯表達式;
-z     空字符串;
-x     是否具有可執行權限
||     單方成立;
&&     雙方都成立表達式。

1. 不帶有else

基礎結構:

if  判斷語句; thencommand
fi
[root@shell ~]# vi if1.sh
[root@shell ~]# cat if1.sh
#!/bin/bash
a=10
if [ $a -gt 4 ] #這里的gt為英文單詞greater than(大于)
then
echo ok
fi
[root@shell ~]# sh if1.sh
ok

在這里插入圖片描述

2. 帶有else(否則的意思)

基礎結構:

if  判斷語句  ; thencommand
elsecommand
fi
[root@shell ~]# vi if2.sh
[root@shell ~]# cat if2.sh
#!/bin/bash
a=10
if [ $a -gt 4 ]
thenecho ok
else echo "not ok"
fi
[root@shell ~]# sh if2.sh
ok

在這里插入圖片描述

3. 帶有elif(相當于再則的意思)

[root@shell ~]# vi if3.sh
[root@shell ~]# cat if3.sh
#!/bin/bash
a=3
if [ $a -gt 4 ]
thenecho ok
elif [ $a -gt 8 ]
thenecho "very ok"
elseecho "not ok"
fi
[root@shell ~]# sh if3.sh
not ok

在這里插入圖片描述

4. 嵌套(if句里在添加if語句)

[root@localhost ~]# vi if4.sh
#!/bin/bash
a=15if [ $a -gt 4 ]
thenif [ $a -lt 20 ]
thenecho "ok"
elseecho "very ok"
fielseecho "not ok"
fi

在這里插入圖片描述

5. 多個條件

[root@shell ~]# cat if5.sh
#!/bin/bashread -p "請輸入任志財的一百米跑步成績:" a
read -p "請輸入王帥的一百米跑步成績:" bif [ $a -gt 9 ] && [ $a -lt 11 ]
then
echo "任志財對王帥說老弟你還得練”
if [ $b -gt 12 ]
then
echo "王帥對任志財說財哥我錯了我再也不敢和你比賽了”
fi[root@shell ~]# sh if5.sh
請輸入任志財的一百米跑步成績:10
請輸入王帥的一百米跑步成績:15
任志財對王帥說老弟你還得練”if [ 15 -gt 12 ]
then
echo 王帥對任志財說財哥我錯了我再也不敢和你比賽了”

在這里插入圖片描述
在這里插入圖片描述

6. if邏輯判斷

shell腳本中if經常用于判斷文檔的屬性,比如判斷是普通文件還是目錄,判斷文件是否有讀、寫、執行權限等。If常用選項如下:

-e:判斷文件或目錄是否存在。
-d:判斷是不是目錄以及是否存在。
-f:判斷是不是普通文件以及是否存在。
-r:判斷是否有讀權限。
-w:判斷是否有寫權限。
-x:判斷是否可執行。
-h: file     hard link(鏈接文件)
-L :file link(鏈接文件)
-b :file     塊設備文件
-c :file 字符設備文件
-p :file     管道文件
-S :file socket套接字文件
-t :file 文件與終端相關聯
-N :file文件最后一次讀取后被修改過
-s :file 文件大小不為0,文件存在且非空
-z:判斷是否為空字符串
-n:判斷是否為非空字符串
注意:root用戶對文件的讀寫比較特殊,即使一個文件沒有給root用戶讀或者寫的權限,root也可以讀或者寫。
[root@localhost ~]# vi test.sh
#!/bin/bash
if [ -d /etc ]; thenif [ -f if1.sh ]; thenif [ -r if1.sh ]; thenif [ ! -w if1.sh ]; then  # !-W 表示數學中的非,即本為ture,非本則為falseecho "文件不具有寫權限"elseecho "文件具有寫權限"fiecho "文件具有讀權限"elseecho "文件不具有讀權限"fiecho "文件存在"elseecho "文件不存在"fi
echo "目錄存在"elseecho "目錄不存在"fi

在這里插入圖片描述

6.2 case判斷

Case判斷基礎格式如下

case 變量 in
value1)                    #不限制value的個數
command
;;                         #一個分支的結束
value2)
command
;;
*)                         #此處*代表其他值
command
;;
esac

在Shell腳本中,case語句是一種多路選擇結構,它允許一個變量等于多個值時分別執行不同的操作。case語句以case關鍵字開始,以esac(case的反寫)關鍵字結束。

為了讓我們能夠更加清晰的理解case邏輯判斷,接下來我們編寫一個腳本來進行實驗:

[root@localhost ~]# vi case.sh
#!/bin/bash
read -p "Please input a number:" nif [ -z "$n" ]thenecho "Please input a number."exit 1fiif [ $n -lt 60 ] && [ $n -ge 1 ]thentag=1
elif [ $n -ge 60 ] && [ $n -lt 80 ]
thentag=2
elif [ $n -ge 80 ] && [ $n -lt 90 ]
thentag=3
thentag=4elsetag=0fi
case $tag in                          #$tag匹配為1,輸出not ok1)echo "not ok";;2)echo "ok";;3)echo "very ok";;4)echo "very good";;*)                                   #$tag匹配除前面1,2,3,4以外的數。elif [ $n -ge 90 ] && [ $n -le 100 ]echo "The number range is 0-100.";;
esac

七、循環控制

7.1. for循環

基礎結構如下

for 變量名 in 循環條件;
do
command
done

案例:
基礎案例

[root@localhost shell]# vi for1.sh
#!/bin/bash
sum=0
for i in `seq 1 10`
dosum=$[$sum+$i]echo $i
done
echo $sum

執行結果:
在這里插入圖片描述
進階案例(9*9乘法表)

[root@shell ~]# vi for2.sh
[root@shell ~]# cat for2.sh
#!/bin/bash
for((i=1;i<10;i++))    #定義i的初始值為1,且這個值不大于9,每次循環加1
dofor((j=1;j<=i;j++))doecho -en "$i*$j=$[i*j]\t" #-n 表示不換行打印,\t表示制表符,屬于轉義字符,-e的作用就是使轉義字符能夠被解釋        doneechodone

在這里插入圖片描述

7.2 while循環

基礎結構

while 條件; do
command
done

用while循環制作99乘法表

[root@shell ~]# vi while.sh
[root@shell ~]# cat while.sh
#!/bin/bashi=1while (( $i<=9 ))doj=1while (( $j<=$i ))doecho -ne "$i*$j=$((i * j))\t"let j++    # let為賦值表達式,即j++ 《=》j=j+1donelet i++echo ""    # 這步操作在于換行done

在這里插入圖片描述

7.3 跳出循環

break在腳本中表示跳出該層循環,示例如下:

[root@shell ~]# vi break1.sh
[root@shell ~]# cat break1.sh
#!/bin/bash
for i in `seq 1 5` 
doecho $iif [ $i -eq 3 ] thenbreak fiecho $i 
done
echo aaaaa

在這里插入圖片描述

7.4 結束本次循環

當在shell腳本中使用continue時,結束的不是整個循環,而是本次循環。忽略continue之下的代碼,直接進行下一次循環。示例如下:

[root@shell ~]# vi continue1.sh
[root@shell ~]# cat continue1.sh
#!/bin/bash
for i in `seq 1 5 `
doecho $iif [ $i == 3 ] thencontinue          #此處continue表示若 $i == 3 則結束本次循環fiecho $i 
done 
echo $i

在這里插入圖片描述

7.5 退出整個腳本

當我們在shell腳本中遇到exit時,其表示直接退出整個shell腳本。示例如下:

[root@shell ~]#  vi exit1.sh
[root@shell ~]# cat exit1.sh
#!/bin/bash
for i in `seq 1 5`
doecho $iif [ $i == 3 ] thenexit fiecho $i 
done
echo aaaa

在這里插入圖片描述
在這里插入圖片描述

八、函數

shell腳本中的函數就是先把一段代碼整理到了一個小單元中,并給這個小單元命名,當我們用到這段代碼時直接調用這個小單元的名字就可以了,這樣很方便,省時省力。但我們需要注意,在shell腳本中,函數一定要寫在前面,因為函數要被調用的,如果還未出現就被調用就會出錯。

基礎格式:

function f_name()                  # function 函數名() 
{                                                     #{
Command                                  #  函數體(即命令序列)
}                                                       #}

8.1 打印出第一個、第二個參數、參數的個數及腳本名

示例如下:

[root@shell ~]# vi fun1.sh
[root@shell ~]# cat fun1.sh
#/bin/bash
input()
{
echo $1 $2 $# $0         # 函數的參數:$1 $2 $# ;$0則是腳本的名字
}
input 1 a b[root@shell ~]# sh fun1.sh
1 a 3 fun1.sh

在這里插入圖片描述

8.2 加法的函數

[root@shell ~]# vi fun2.sh
[root@shell ~]# cat fun2.sh
#!/bin/bash
sum()
{
s=$[$1+$2]
echo $s
}
sum 1 2

在這里插入圖片描述

8.3 獲得一個網卡的ip地址

[root@shell ~]# vi fun3.sh
[root@shell ~]# cat fun3.sh
#!/bin/bash
ip()
{
ifconfig |grep -A1 "$1: " |tail -1 |awk '{print $2}'
}
read -p "Please input the eth name: " e
myip=`ip $e`
echo "$e address is $myip"

在這里插入圖片描述

8.4 返回值與傳參

add() {echo $(($1 + $2))
}
result=$(add 3 5)  # 通過 $? 或命令替換獲取結果
echo "3+5=$result"

8.5 函數庫封裝

math_lib.sh:

#!/bin/bash
square() {echo $(($1 * $1))
}
1
2
3
4

主腳本:

source math_lib.sh
echo "5的平方: $(square 5)"

九、正則表達式

概述

正則表達式是你所定義的模式模板, Linux工具可以用它來過濾文本。 Linux 工具(比如sed編輯器或gawk程序)能夠在處理數據時使用正則表達式對數據進行模式匹配。如果數據匹配模式,它就會被接受并進一步處理;

如果數據不匹配模式,它就會被濾掉。

它主要用于字符串的分割,匹配、査找及替換操作。即正則表達式是一種文本模式,該模式描述在搜索文本時要匹配的一個或多個字符串

簡單來說就是通過一些特殊字符的排序,用以刪除、查找、替換一行或者多行文字字符串的程序。

1.基礎正則

基礎正則常見元字符(支持的工具:grep、egrep、sed、awk)

\ :轉義字符,用于取消特殊符號的含義,例:\!\n、\$等
^ :匹配字符串開始的位置,例:^a、^the、^#、^[a-z]
$ :匹配字符串結束的位置,例: word$、 ^$匹配空行
*:匹配除\n之外的任意的一個字符,例: lo.*k、lo.k、l..k
.*:匹配任意長度的字符
+:匹配前面的字符出現過最少一次
\{n\} : 匹配前面一個字符n次,例: lo\{2\}k、 '[0-9]\{2\}'匹配兩位數字
\{n,\} : 匹配前面一個字符不少于n次,例: lo\{2,\}k、 '[0-9]\{2,\}'匹配兩位及兩位以上數字
\{n,m\} : 匹配前面一個字符n到m次,例: lo\{2,3\}k、 '[0-9]\{2,3\}'匹配兩位到三位數字

注: egrep、 awk使用{n}、{n,}、 {n, m}匹配時“{}"前不用加“\”

2. 常用命令

(1)Sort排序:
以行對文件進行排序
可以通過linux自帶的man手冊去查看更多的命令
在這里插入圖片描述
在這里插入圖片描述

(2)查看一些常用命令可用 命令 –help
在這里插入圖片描述

tac:倒序打印文件
rev:反向打印每一行
cut:字符切割,常用選項-d 分割,-f輸出第幾段
tr:替換或刪除字符
seq:打印序列化數字
uniq:去重 -c 打印出現次數、-u :打印不重復的行

3. 三劍客(核心)

3.1 grep

1. 功能
篩選過濾出包含<匹配字符串>的<整行>
例如:篩選出以#開頭的打印出來
在這里插入圖片描述
2.語法

grep [選項]   PATTERN  [FILE....]
PATTERN:就是正則表達式,默認情況下,grep命令使用基本正則

3.選項

-i   表示忽略大小寫
[root@shell ~]# grep -i "rzc" grep.sh     # “”里面表示要找的內容  后面加上文件的路徑

在這里插入圖片描述

-E 表示啟用<擴展正則>
,將模式 PATTERN 作為一個擴展的正則表達式來解釋
[root@shell ~]# grep -E "^#|^$" grep.sh

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

-o只顯示匹配的行中與 PATTERN 相匹配的部分。
默認情況下,是輸出包含<匹配內容><一行數據>

在這里插入圖片描述

-v表示僅輸出<不匹配的數據行> 注意是<不匹配的行>,也就是取反
^和$代表空行

在這里插入圖片描述

-B 打印出匹配的行之前的上文 NUM 行。
在相鄰的匹配組之間將會打印內容是 -- 的一行。

在這里插入圖片描述

-A打印出緊隨匹配的行之后的下文NUM行。
在相鄰的匹配組之間將會打印內容是 -- 的一行。

在這里插入圖片描述

-C顯示匹配的<數據行><行總數>

在這里插入圖片描述

3.2 sed

1. 基本語法和功能

語法格式:sed [選項] ‘腳本命令’ 輸入文件。例如,sed’s/old/new/g’ file.txt,其中s表示替換操作,old是要被替換的字符串,new是替換后的字符串,g表示全局替換(即文件中所有匹配的字符串都被替換),file.txt是操作的目標文件。

功能概述:sed是一個流編輯器,主要用于對文本文件進行編輯操作。它可以在不打開文件的情況下,對文件內容進行查找、替換、刪除、插入等操作。sed的操作是基于行的,它逐行讀取文件內容,按照指定的腳本命令進行處理,然后輸出結果。

2. 替換操作 (s命令)

簡單替換:
示例:sed’s/hello/hi/’ file.txt,此命令會將file.txt文件中每行第一次出現的 “hello” 替換為 “hi”。如果要進行全局替換,需要在替換命令最后添加g選項,如sed’s/hello/hi/g’ file.txt。

使用正則表達式進行替換:
sed支持使用正則表達式來匹配要替換的內容。例如,sed’s/[0 - 9]+/number/’ file.txt,會將file.txt文件中每行出現的數字(一個或多個數字)替換為 “number”。

替換部分匹配的字符串:
可以通過在替換命令中使用&符號來引用匹配的字符串部分。例如,sed’s/(\w+), (\w+)/\2, \1/’ file.txt(在支持擴展正則表達式的情況下),假設文件中有 “John, Doe” 這樣的內容,此命令會將其轉換為 “Doe, John”,其中\1和\2分別代表第一個和第二個括號內匹配的內容。

3. 刪除操作 (d命令)

刪除匹配行:
示例:sed ‘/^#/d’ file.txt,此命令會刪除file.txt文件中所有以 “#” 開頭的行。符號表示行的開頭,所以#匹配以 “#” 開頭的行。

根據條件刪除行:
可以結合多個條件來刪除行。例如,sed -n ‘/pattern1/ { /pattern2/!d }’ file.txt(-n選項用于抑制默認輸出,只輸出經過腳本命令處理后的行),這個命令會刪除file.txt中包含 “pattern1” 但不包含 “pattern2” 的行。

4.插入和追加操作(i和a命令)

插入操作(i):
示例:sed ‘1i This is a new line’ file.txt,會在file.txt文件的第一行之前插入 “This is a new line”。

追加操作(a):
示例:sed ‘$a This is an appended line’ file.txt,會在file.txt文件的最后一行之后追加 “This is an appended line”。

5.讀取和寫入文件(r和w命令)

讀取文件(r):
示例:sed ‘3r other_file.txt’ file.txt,會在file.txt文件的第三行之后讀取并插入other_file.txt的內容。

寫入文件(w):
示例:sed -n ‘/pattern/w output_file.txt’ file.txt,會將file.txt中包含 “pattern” 的行寫入到output_file.txt文件中。

6.在shell腳本中的應用場景

配置文件修改:
在腳本中,可以使用sed修改配置文件。例如,修改nginx.conf文件中服務器監聽端口,sed -i’s/listen 80/listen 8080/g’ nginx.conf,-i選項表示直接在原文件上進行修改。

日志文件處理:
對于日志文件,可以使用sed提取或清理特定的日志行。如sed -n ‘/ERROR/p’ log_file.txt會只打印log_file.txt中包含 “ERROR” 的行,用于快速定位錯誤日志。

3.3 awk

1.打印操作

打印整行:
命令格式:awk ‘{print $0}’ 文件名。例如:awk ‘{print $0}’ log.txt會將log.txt文件中的每一行內容都打印出來。這在查看文件的原始內容時非常有用,比如查看配置文件或者簡單的文本記錄文件。

打印指定列:
命令格式:awk ‘{print $列數}’ 文件名。例如:awk ‘{print $1}’ data.csv,假設data.csv是一個以逗號分隔的文件(如包含姓名、年齡、地址等信息),這個命令會打印出每一行的第一列內容,也就是姓名列。如果想打印多列,可以用逗號分隔,如awk ‘{print $1, $3}’ file.txt會打印第一列和第三列的內容。

2.條件判斷操作

基于文本內容篩選行:
命令格式:awk ‘/正則表達式/ {動作}’ 文件名。例如:awk ‘/error/ {print $0}’ error.log會將error.log文件中包含 “error” 字樣的行全部打印出來。這在日志文件分析中經常使用,用于快速定位包含特定錯誤信息的行。

基于列內容篩選行:
命令格式:awk ‘$列數 比較運算符 值 {動作}’ 文件名。例如:awk ‘$2 > 10 {print $0}’ numbers.txt,假設numbers.txt是一個包含數字的文件,這個命令會將第二列數字大于 10 的行全部打印出來。比較運算符可以是>(大于)、<(小于)、==(等于)、>=(大于等于)、<=(小于等于)和!=(不等于)。

3.數據統計操作

計算列總和:
命令格式:awk ‘{sum += $列數} END {print sum}’ 文件名。例如:awk ‘{sum += $3} END {print sum}’ sales.csv,假設sales.csv是一個銷售數據文件,第三列是銷售額,這個命令會計算出所有行銷售額的總和并打印出來。

計算列平均值:
命令格式:awk ‘{sum += $列數; count++} END {print sum/count}’ 文件名。例如:awk ‘{sum += $4; count++} END {print sum/count}’ scores.csv,假設scores.csv是一個學生成績文件,第四列是某一科目成績,這個命令會計算出該科目成績的平均值。

4.文本格式化操作

自定義輸出格式:
命令格式:awk ‘{printf “格式化字符串”, $列數}’ 文件名。例如:awk ‘{printf “%-10s %-10s\n”, $1, $2}’ contacts.txt,假設contacts.txt是一個包含聯系人姓名和電話的文件,這個命令會將姓名和電話以左對齊、寬度為 10 個字符的格式輸出,并且每行末尾添加換行符。格式化字符串中常用的格式控制符有%s(字符串)、%d(整數)、%f(浮點數)等,-表示左對齊,數字表示寬度。

字符串拼接與替換:
命令格式:awk ‘{new_column = $列數1 “連接字符” $列數2; print new_column}’ 文件名。例如:awk ‘{new_column = $1 " - " $2; print new_column}’ products.txt,假設products.txt是一個產品信息文件,第一列是產品名稱,第二列是產品型號,這個命令會將名稱和型號用 “-” 連接起來并打印新的列。也可以使用sub或gsub函數進行字符串替換,如awk ‘{sub(“舊字符串”, “新字符串”, $列數); print $列數}’ 文件名。

十、錯誤處理與調試

10.1 錯誤捕獲

# 立即退出遇到錯誤
set -e
# 捕獲錯誤并處理
trap "echo '發生錯誤!退出狀態: $?'" ERR
# 忽略錯誤
command || true

10.2 調試技巧

# 啟用調試模式
set -x
echo "調試信息可見"
set +x
# 輸出行號
echo "當前行號: $LINENO"

10.3 日志記錄

exec > >(tee -a script.log) 2>&1
echo "日志將同時輸出到屏幕和文件"

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

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

相關文章

k8s部署,pod管理,控制器,微服務,集群儲存,集群網絡及調度,集群認證

k8s部署 k8s中容器的管理方式 ? Kubernetes集群創建方式 centainerd 默認情況下&#xff0c;K8S在創建集群時使用的方式 docker docker使用的普記錄最高&#xff0c;雖然K8S在1.24版本后已經費力了kubelet對docker的支持&#xff0c;但時可以借助cri-docker方式來實現集…

JAVA限流方法

在 Java 項目中限制短時間內的頻繁訪問&#xff08;即接口限流&#xff09;&#xff0c;是保護系統資源、防止惡意攻擊或高頻請求導致過載的重要手段。常見實現方案可分為單機限流和分布式限流&#xff0c;以下是具體實現方式&#xff1a;一、核心限流算法無論哪種方案&#xf…

性能比拼: .NET (C#) vs. Fiber (Go)

本內容是對知名性能評測博主 Anton Putra .NET (C#) vs. Fiber (Go): Performance (Latency - Throughput - Saturation - Availability) 內容的翻譯與整理, 有適當刪減, 相關指標和結論以原作為準 在本視頻中&#xff0c;我們將對比 C# 與 .NET 框架和 Golang 的表現。在第一個…

信譽代幣的發行和管理機制是怎樣的?

信譽代幣的發行與管理機制是區塊鏈技術與經濟模型深度融合的產物&#xff0c;其核心在于通過代碼和社區共識構建可量化、可驗證的信任體系。以下從技術架構、經濟模型、治理機制三個維度展開分析&#xff0c;并結合具體案例說明&#xff1a;一、發行機制&#xff1a;行為即價值…

神經網絡|(十二)概率論基礎知識-先驗/后驗/似然概率基本概念

【1】引言 前序學習進程中&#xff0c;對貝葉斯公式曾經有相當粗糙的回歸&#xff0c;實際上如果我們看教科書或者網頁&#xff0c;在講貝葉斯公式的時候&#xff0c;會有幾個名詞反復轟炸&#xff1a;先驗概率、后驗概率、似然概率。 今天就來把它們解讀一下&#xff0c;為以…

使用UE5開發《紅色警戒3》類戰略養成游戲的硬件配置指南

從零開始&#xff0c;學習 虛幻引擎5&#xff08;UE5&#xff09;&#xff0c;開始游戲開發之旅&#xff01;本文章僅提供學習&#xff0c;切勿將其用于不法手段&#xff01;開發類似《紅色警戒3》級別的戰略養成游戲&#xff0c;其硬件需求遠超普通2D或小型3D項目——這類游戲…

Vue2+Vue3前端開發_Day12-Day14_大事件管理系統

參考課程: 【黑馬程序員 Vue2Vue3基礎入門到實戰項目】 [https://www.bilibili.com/video/BV1HV4y1a7n4] ZZHow(ZZHow1024) 項目收獲 Vue3 composition APIPinia / Pinia 持久化處理Element Plus&#xff08;表單校驗&#xff0c;表格處理&#xff0c;組件封裝&#xff09…

[ACTF新生賽2020]明文攻擊

BUUCTF在線評測BUUCTF 是一個 CTF 競賽和訓練平臺&#xff0c;為各位 CTF 選手提供真實賽題在線復現等服務。https://buuoj.cn/challenges#[ACTF%E6%96%B0%E7%94%9F%E8%B5%9B2020]%E6%98%8E%E6%96%87%E6%94%BB%E5%87%BB下載查看&#xff0c;一個壓縮包和一張圖片。壓縮包需要密…

關于日本服務器的三種線路講解

租用日本服務器時&#xff0c;哪種線路選擇更適合?當初次接觸跨境業務的站長們著手租用日本服務器時&#xff0c;會發現不同服務商提供的網絡線路五花八門&#xff0c;從陌生的運營商名稱到復雜的技術參數&#xff0c;常常使其感到眼花繚亂。為了幫助大家理清思路&#xff0c;…

【大白話解析】 OpenZeppelin 的 MerkleProof 庫:Solidity 默克爾證明驗證工具全指南??(附源代碼)

?? 一、Merkle Tree 是什么?為什么要驗證它? 想象你有一個名單,比如: ["Alice", "Bob", "Charlie", "Dave"] 你想讓別人驗證:“我(比如 Alice)是不是在這個名單里?”,但不想把整個名單都放在區塊鏈上(太貴!)。 于是你…

機械學習綜合練習項目

數據集合完整項目文件已經上傳一、項目介紹案例介紹 案例是針對“紅酒.csv”數據集&#xff0c;在紅葡萄酒質量分析的場景 中&#xff0c;利用多元線性回歸來探索紅葡萄酒的不同化學成分如何共同 影響其質量評分。在建立線性回歸模型之后&#xff0c;當給出了紅葡萄酒 的新的一…

第3篇:配置管理的藝術 - 讓框架更靈活

前言 在前一章中&#xff0c;我們設計了強大的注解API。本章將深入探討配置管理系統的設計&#xff0c;學習如何將注解中的聲明式配置轉換為運行時可用的配置對象。 配置管理的核心挑戰 在我們的框架中&#xff0c;配置來源有三個層級&#xff1a;主要挑戰&#xff1a; &#x…

發版混亂怎么規范

你是否經歷過這種場景&#xff1a;臨到發版&#xff0c;一堆功能代碼擠在一起&#xff0c;測試分不清范圍&#xff0c;修復一個Bug可能引發三個新Bug&#xff1f;發布過程像一場豪賭&#xff1f;問題的核心往往在于分支策略和流程的混亂。今天&#xff0c;我們就來建立一套在絕…

【golang長途旅行第30站】channel管道------解決線程競爭的好手

channel 為什么需要channel 使用全局變量加鎖同步來解決goroutine的競爭&#xff0c;可以但不完美難以精確控制等待時間?&#xff08;主線程無法準確知道所有 goroutine 何時完成&#xff09;。全局變量容易引發競態條件?&#xff08;即使加鎖&#xff0c;代碼復雜度也會增加…

蘋果XR芯片介紹

蘋果的 XR 芯片技術主要體現在 A 系列、M 系列處理器以及專為空間計算設計的 R1 協處理器中。以下從技術架構、產品迭代和綜合對比三個維度展開分析&#xff1a;一、技術架構解析1. A 系列芯片&#xff08;以 A12 Bionic 為例&#xff09;制程工藝&#xff1a;7nm&#xff08;臺…

達夢數據庫巡檢常用SQL(三)

達夢數據庫巡檢常用SQL(三) 數據庫SQL運行檢查 數據庫SQL運行檢查 死鎖的事務情況: SELECT TO_CHAR(HAPPEN_TIME,YYYY-MM-DD HH24:MI:SS) HAPPEN_TIME,SQL_TEXT FROM V$DEADLOCK_HISTORY WHERE HAPPEN_TIME >DATEADD(DAY,-30,

基于SpringBoot的校園周邊美食探索及分享平臺

1. 項目簡介 項目名稱&#xff1a;校園周邊美食探索及分享平臺 項目背景&#xff1a;針對校園師生對周邊美食信息的需求&#xff0c;構建一個集美食推薦、鑒賞、評論互動及社交功能于一體的平臺&#xff0c;幫助用戶發現優質美食資源并進行分享交流。 主要目標&#xff1a; 提供…

Go數據結構與算法-常見的排序算法

雖然看過別人寫了很多遍&#xff0c;而且自己也寫過很多遍&#xff08;指的是筆記&#xff09;&#xff0c;但是還是要寫的就是排序算法。畢竟是初學Go語言&#xff0c;雖然之前寫過&#xff0c;但是還是打算再寫一遍。主要包括插入排序、選擇排序、冒泡排序、快速排序、堆排序…

第 6 篇:目標規則與負載均衡 - `DestinationRule` 詳解

系列文章:《Istio 服務網格詳解》 第 6 篇:目標規則與負載均衡 - DestinationRule 詳解 本篇焦點: 深入理解 DestinationRule 的核心作用:定義流量在到達目的地之后的行為。 詳細剖析其三大核心功能:服務子集 (Subsets), 流量策略 (Traffic Policy), TLS 設置。 動手實戰…

一個簡潔的 C++ 日志模塊實現

一個簡潔的 C 日志模塊實現 1. 引言 日志功能在軟件開發中扮演著至關重要的角色&#xff0c;它幫助開發者追蹤程序執行過程、診斷問題以及監控系統運行狀態。本文介紹一個使用 C 實現的輕量級日志模塊&#xff0c;該模塊支持多日志級別、線程安全&#xff0c;并提供了簡潔易用…