Bo2SS

Bo2SS

7 Shell程式設計基礎

高級語言、腳本語言、解釋型語言:xxx.sh,一般基於 bash

課程內容#

第一個 Shell 腳本#

#!/bin/bash
#註解
echo "Hello"
  • 第一行 #! 指定解釋器,只在第一行才有效
  • 註解:"#"

變量#

a=123
a=hello
a=`pwd`
PATH=${PATH}:path  # 變量後接字符串,可以直接拼接字符串
# 【注意】":a"有特殊含義,會指到當前路徑
  • 不需要定義變量類型【弱類型語言】
    • 如 a=123 可以是字符串,也可以是整數
  • "" 有特殊含義
    • img
    • 可用雙引號包住 a,如 a=$a:"a" 或 a=$a"",得到 a=123

特殊變量#

位置變量

  • image-20201218170251055

結果:

  • image-20201215174953312
  • $n:如果 n>9,需要用大括號括起來

  • $@ 和 $* 的區別在於:傳入參數分別被雙引號包圍、且 $ 變量也被雙引號包圍時,"$@" 會將所有的參數分開【一般情況】,而 "$*" 會將所有的參數作為一個整體

  • $#:不算 $0

狀態變量

  • $?:【上一條】指令執行結果,0—— 成功,非 0—— 不成功
    • 圖片
    • 便於腳本自動判斷指令成功與否
  • $$、$!:當前進程、最後運行的後台進程的 PID,一般用於自動化測試、多腳本交互場景

輸入輸出#

  • 輸入:read
    • 圖片
    • -p:顯示友好提示,需在 bash 下使用
    • -s:靜默模式
    • -t:輸入等待時長,超時結束 (單位:s)
  • 輸出:echo
    • -e:開啟轉義
  • 輸出:printf
    • 和 C 語言的 printf 非常像!
    • 圖片
    • [PS] ! 和 \n 放一起有特殊含義,需要分開
      • bash 下需要分開
      • zsh 下可以分開,或用 \ 轉義
      • 一般對於特殊符號—— 菜鳥教程,需要警覺!

函數#

  • 圖片
  • 沒有形參

  • 定義:寫法很多,function、()、{} 組合搭配,第 3 種更類似 C 語言寫法

  • 調用:函數名 參數...

    • 圖片
    • 加 function 方便閱讀
  • ❗【注意】shell 中函數 return 的返回值有限制,範圍是 0-255,溢出會循環換算

流程控制#

do——done、if——then——fi、case——esac

【重點】TEST 表達式⭐#

  • 可判斷類型:字符串、整型、文件
  • ❗ 【注意】條件為真時,返回 0,否則返回非 0
    • Linux 中命令的返回值也是如此,0 才代表成功
  • [PS]
    • STRING1 = STRING2 也可以用 == 【推薦後者,兩個中括號 [[]] 支持】
    • -G FILE:文件存在並且被有效組 ID 擁有
      • 如果組被解散了,則組控制的文件的組 ID 就是無效的
    • 具體可查閱 man 手冊:man test

分支結構#

if

case

  • 圖片
  • 分號;;不能沒有!相當於 break,加了 break 也要有

  • 默認情況可用 *)

  • case 用的較少,一般用來做菜單,比 if 更美觀

循環結構#

for

  • 利用 seq 生成序列

  • 圖片
  • 利用 ls 的匹配規則

  • 圖片
  • for 的兩種形式

  • 圖片
  • 雙小括號 (()) 中的內容只要符合 C 語言運算規則即可,變量可以不使用變量前綴 $,可以寫 i++,平常不可以用 ++

while

  • 圖片
  • 同樣適用 test 表達式

  • 初始化 num 變量,否則

    • 第一次 echo $num 時,$num 是空值,表現為空行
    • 當遇到後面的 + 1 時,系統判定它為整數類型,才當做整數用

until

  • 圖片
  • 與 while 唯一的區別在於:until 寫的是停止條件,while 寫的是循環條件

陣列#

  • 圖片
  • 陣列賦值【方式①】和調用

  • 圖片
  • 【常用的陣列操作】還可以輸出陣列元素的下標,見後

  • 圖片
  • 聲明陣列:declare -a num,方便閱讀,不聲明也可以 [弱類型語言]

  • 賦值【方式②、③】

    • num[2]=10 num[5]=7 num[100]=3.2.4
    • num=(1 a b 10)
  • 陣列元素不一定要連續賦值,且可以為任意類型

    • 【常用的陣列操作】加!:輸出所有陣列元素對應的下標,可以看出不是連續的

【其它陣列操作】

  • 圖片
  • +=:追加

  • unset:刪除陣列,或元素 [通過下標刪除]

  • [PS] 賦值方式③對多個空格也只作一個分隔符

應用

  • 圖片
  • 可以用來存儲文件名列表

  • 【注意】賦值方式③給陣列賦值是以空格作為分隔符,所以如果文件名裡有空格,需要特殊處理

  • 【PS】素數篩、線性篩

隨堂練習#

1~100 的偶數和#

  • 圖片
  • $[ ] 可用來做整數運算

  • seq 效率稍低

暴力求素數#

  • 圖片
  • 函數的 return 值

    • 通過 $? 獲得,在調用函數後 echo $? 即可,但是 return 值有範圍限制 0~255!
    • 通過命令替換符 `` 取到
  • 注意對於循環變量 i 的衝突問題:定義局部變量

  • 🆒調試程序

    • 習慣:適當的 echo 輸出
    • 全局調試:bash -x *.sh
    • 局部調試:set -x [調試代碼區域] set +x

素數篩#

  • img
  • 方式一方便操作素數,且輸出時可減少判斷

  • 方式二還可以操作合數

【暴力法、素數篩 2 種方法效果比較】求 2~10000 的素數和

img

  • 9.prime.sh 暴力法 —— 10.prime.sh 素數篩

附加知識點#

  • .sh 腳本可以直接 bash 或 source 執行,如果要使用./ 需要有可執行權限
  • set -x 可以開啟 shell 調試
  • Shell 命令替換:將命令的輸出結果賦值給變量——C 語言中文網
    • $() 支持嵌套,反引號 `` 不行
    • $() 僅在 Bash 中有效 [似乎 zsh、sh 都支持],而反引號 `` 可在多種 Shell 中使用
  • 雙小括號 (()) 中的內容
    • 只要符合 C 語言運算規則即可
    • 變量可以不使用變量前綴 $
    • 可以寫 i++,平常不可以用 ++
  • ⭐在 Shell 中,變量還未定義時,其值為空,echo 輸出表現為空行
  • ⭐空格問題【嚴格】
    • 賦值語句:= 兩側不能有空格
    • TEST 表達式相關:[[]] 兩端必須有空格
  • 對於變量名 i,如果想將 $i 與_i 拼接,用 $i_i,會去找變量 i_i,所以要用 ${i}_i

Tips#

  • 寫 Shell 腳本
    • 不要太考慮性能,單純做數學計算效率低
    • 為的是快速解決一個問題,用來規劃所有任務的流程
    • 做操作前記得加【備份】操作
    • 一般是讓系統做事情,難於操作特定的程序做事情
      • 程序一般有自己的參數設置,但不具有普適性
  • API 一般指服務
  • Shell 風格指南——Google 開源項目風格指南 ——Shell 編程規範
  • Shell 腳本多行註解和單行註解的方法—— 博客
:<<!
[要註解的代碼]
!
  • 可以了解let—— 菜鳥教程,方便的語法

課程速記#

  • 圖片
  • 圖片
  • 圖片
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。