linux學習day3——shell指令碼上

Sunyehh發表於2024-10-27

shell語法

  • 概論
  • 註釋
  • 變數
  • 預設變數
  • 陣列
  • expr命令
  • read命令
  • echo命令
  • printf命令
  • test命令與判斷符號[]
  • 判斷語句
  • 迴圈語句
  • 函式
  • exit命令
  • 檔案重定向
  • 引入外部指令碼

1.shell語法——概論

概論

shell是我們透過命令列與作業系統溝通的語言。

shell指令碼可以直接在命令列中執行,也可以將一套邏輯組織成一個檔案,方便複用。
AC Terminal中的命令列可以看成是一個“shell指令碼在逐行執行”。

注:AC Terminal相當於linux,命令列終端。

Linux中常見的shell指令碼有很多種,常見的有:

Bourne Shell(/usr/bin/sh或/bin/sh)
Bourne Again Shell(/bin/bash)
C Shell(/usr/bin/csh)
K Shell(/usr/bin/ksh)
zsh
…

Linux系統中一般預設使用bash,所以接下來講解bash中的語法。
檔案開頭需要寫#! /bin/bash,指明bash為指令碼直譯器。


學習技巧

不要死記硬背,遇到含糊不清的地方,可以在AC Terminal裡實際執行一遍。

指令碼示例

新建一個test.sh檔案,內容如下:

#! /bin/bash
echo "Hello World!"

###執行方式 作為可執行檔案
acs@9e0ebfcd82d7:~$ chmod +x test.sh  # 使指令碼具有可執行許可權
acs@9e0ebfcd82d7:~$ ./test.sh  # 當前路徑下執行
Hello World!  # 指令碼輸出
acs@9e0ebfcd82d7:~$ /home/acs/test.sh  # 絕對路徑下執行
Hello World!  # 指令碼輸出
acs@9e0ebfcd82d7:~$ ~/test.sh  # 家目錄路徑下執行
Hello World!  # 指令碼輸出

用直譯器執行

acs@9e0ebfcd82d7:~$ bash test.sh
Hello World!  # 指令碼輸出

2.shell語法——註釋

單行註釋

每行中#之後的內容均是註釋。

# 這是一行註釋

echo 'Hello World'  #  這也是註釋

多行註釋

格式:

:<<EOF
第一行註釋
第二行註釋
第三行註釋
EOF

其中EOF可以換成其它任意字串。例如:

:<<abc
第一行註釋
第二行註釋
第三行註釋
abc

:<<!
第一行註釋
第二行註釋
第三行註釋
!

3. shell語法——變數

定義變數

定義變數,不需要加$符號,例如:

name1='yxc'  # 單引號定義字串
name2="yxc"  # 雙引號定義字串
name3=yxc    # 也可以不加引號,同樣表示字串

使用變數

使用變數,需要加上$符號,或者${}符號。花括號是可選的,主要為了幫助直譯器識別變數邊界。

name=yxc
echo $name  # 輸出yxc
echo ${name}  # 輸出yxc
echo ${name}acwing  # 輸出yxcacwing

只讀變數

使用readonly或者declare可以將變數變為只讀。

name=yxc
readonly name
declare -r name  # 兩種寫法均可

name=abc  # 會報錯,因為此時name只讀

刪除變數

unset可以刪除變數。

name=yxc
unset name
echo $name  # 輸出空行

變數型別

  1. 自定義變數(區域性變數)
    子程序不能訪問的變數
  2. 環境變數(全域性變數)
    子程序可以訪問的變數

自定義變數改成環境變數:

acs@9e0ebfcd82d7:~$ name=yxc  # 定義變數
acs@9e0ebfcd82d7:~$ export name  # 第一種方法
acs@9e0ebfcd82d7:~$ declare -x name  # 第二種方法

環境變數改為自定義變數:

acs@9e0ebfcd82d7:~$ export name=yxc  # 定義環境變數
acs@9e0ebfcd82d7:~$ declare +x name  # 改為自定義變數

字串

字串可以用單引號,也可以用雙引號,也可以不用引號。

單引號與雙引號的區別:

  • 單引號中的內容會原樣輸出,不會執行、不會取變數;
  • 雙引號中的內容可以執行、可以取變數;
name=yxc  # 不用引號
echo 'hello, $name \"hh\"'  # 單引號字串,輸出 hello, $name \"hh\"
echo "hello, $name \"hh\""  # 雙引號字串,輸出 hello, yxc "hh"

獲取字串長度

name="yxc"
echo ${#name}  # 輸出3

提取子串

name="hello, yxc"
echo ${name:0:5}  # 提取從0開始的5個字元

4. shell語法——預設變數

檔案引數變數

在執行shell指令碼時,可以向指令碼傳遞引數。$1是第一個引數,$2是第二個引數,以此類推。特殊的,$0是檔名(包含路徑)。例如:

建立檔案test.sh

#! /bin/bash

echo "檔名:"$0
echo "第一個引數:"$1
echo "第二個引數:"$2
echo "第三個引數:"$3
echo "第四個引數:"$4

然後執行該指令碼:

acs@9e0ebfcd82d7:~$ chmod +x test.sh 
acs@9e0ebfcd82d7:~$ ./test.sh 1 2 3 4
檔名:./test.sh
第一個引數:1
第二個引數:2
第三個引數:3
第四個引數:4

其它引數相關變數

引數 說明
$# 代表檔案傳入的引數個數,如上例中值為4
$* 由所有引數構成的用空格隔開的字串, 如上例中值為
$@ 每個引數分別用雙引號括起來的字串,如上例中值為
$$ 指令碼當前執行的程序ID
$? 上一條命令的退出狀態(注意不是stdout,而是exit code)。0表示正常退出,其他值表示錯誤
$(command) 返回command這條命令的stdout(可巢狀)
command 返回command這條命令的stdout(不可巢狀)

5. shell語法——陣列

陣列中可以存放多個不同型別的值,只支援一維陣列,初始化時不需要指明陣列大小。
陣列下標從0開始。

定義

陣列用小括號表示,元素之間用空格隔開。例如:

array=(1 abc "def" yxc)
也可以直接定義陣列中某個元素的值:

array[0]=1
array[1]=abc
array[2]="def"
array[3]=yxc

讀取陣列中某個元素的值

格式:

${array[index]}
例如:

array=(1 abc "def" yxc)
echo ${array[0]}
echo ${array[1]}
echo ${array[2]}
echo ${array[3]}

讀取整個陣列

格式:

${array[@]}  # 第一種寫法
${array[*]}  # 第二種寫法

例如:

array=(1 abc "def" yxc)

echo ${array[@]}  # 第一種寫法
echo ${array[*]}  # 第二種寫法

陣列長度

類似於字串

${#array[@]}  # 第一種寫法
${#array[*]}  # 第二種寫法

例如:

array=(1 abc "def" yxc)

echo ${#array[@]}  # 第一種寫法
echo ${#array[*]}  # 第二種寫法

6. shell語法——expr命令

expr命令用於求表示式的值,格式為:

expr 表示式

表示式說明:

  • 用空格隔開每一項
  • 用反斜槓放在shell特定的字元前面(發現表示式執行錯誤時,可以試試轉義)
  • 對包含空格和其他特殊字元的字串要用引號括起來
  • expr會在stdout中輸出結果。如果為邏輯關係表示式,則結果為真時,stdout輸出1,否則輸出0。
  • expr的exit code:如果為邏輯關係表示式,則結果為真時,exit code為0,否則為1。

字串表示式

  • length STRING
    返回STRING的長度

  • index STRING CHARSET
    CHARSET中任意單個字元在STRING中最前面的字元位置,下標從1開始。如果在STRING中完全不存在CHARSET中的字元,則返回0。

  • substr STRING POSITION LENGTH
    返回STRING字串中從POSITION開始,長度最大為LENGTH的子串。如果POSITIONLENGTH為負數,0或非數值,則返回空字串。

示例:

str="Hello World!"

echo `expr length "$str"`  # ``不是單引號,表示執行該命令,輸出12
echo `expr index "$str" aWd`  # 輸出7,下標從1開始
echo `expr substr "$str" 2 3`  # 輸出 ell

整數表示式

expr支援普通的算術操作,算術表示式優先順序低於字串表示式,高於邏輯關係表示式。

  • + -
    加減運算。兩端引數會轉換為整數,如果轉換失敗則報錯。

  • / %
    乘,除,取模運算。兩端引數會轉換為整數,如果轉換失敗則報錯。

  • () 可以改變優先順序,但需要用反斜槓轉義

示例:

a=3
b=4

echo `expr $a + $b`  # 輸出7
echo `expr $a - $b`  # 輸出-1
echo `expr $a \* $b`  # 輸出12,*需要轉義
echo `expr $a / $b`  # 輸出0,整除
echo `expr $a % $b` # 輸出3
echo `expr \( $a + 1 \) \* \( $b + 1 \)`  # 輸出20,值為(a + 1) * (b + 1)

邏輯關係表示式

  • |
    如果第一個引數非空且非0,則返回第一個引數的值,否則返回第二個引數的值,但要求第二個引數的值也是非空或非0,否則返回0。如果第一個引數是非空或非0時,不會計算第二個引數。

  • &
    如果兩個引數都非空且非0,則返回第一個引數,否則返回0。如果第一個參為0或為空,則不會計算第二個引數。

  • < <= = == != >= >
    比較兩端的引數,如果為true,則返回1,否則返回0。”==”是”=”的同義詞。”expr”首先嚐試將兩端引數轉換為整數,並做算術比較,如果轉換失敗,則按字符集排序規則做字元比較。

  • () 可以改變優先順序,但需要用反斜槓轉義

示例:

a=3
b=4

echo `expr $a \> $b`  # 輸出0,>需要轉義
echo `expr $a '<' $b`  # 輸出1,也可以將特殊字元用引號引起來
echo `expr $a '>=' $b`  # 輸出0
echo `expr $a \<\= $b`  # 輸出1

c=0
d=5

echo `expr $c \& $d`  # 輸出0
echo `expr $a \& $b`  # 輸出3
echo `expr $c \| $d`  # 輸出5
echo `expr $a \| $b`  # 輸出3

作者:yxc
連結:https://www.acwing.com/blog/content/9688/
來源:AcWing

相關文章