即學活用ShellProgramming筆記 - 好康爆報

即學活用ShellProgramming筆記

閱讀數: 4

字體大小設置: 16px

會買這本書,是因為當初 Anna 在精誠資訊時,公司定時會有特價書清單供員工購買,就請她幫忙買囉!呵!這本書真的幫助我很多。自己會做筆記(當然不是只有書上的而已),因為蠻常查的,就轉到雲端(比較方便查)來囉!雖然網路類似文章一大堆,呵!就順便增加一下瀏覽數囉!

即學活用ShellProgramming筆記

相關:Bash Script 語法解析Linux Shell Script 初學

指令快速簡索

保留字與內建字元  

.(句點)

將句點之後的指令直接在現行shell中執行,而不是在另外變成child process。

:(冒號)

no-op指令,空命令,本指令並不執行任何指令,只是用來幫助if之類的語法完整,不致發生錯誤。

!!

(bash)重新執行最後一次執行的指令。

alias

(ksh及bash)別名,縮短輸入常用指令的時間。

bg

(ksh及bash)讓暫停在背景中的行程在背景中繼續執行。

break

跳出目前的for,while或until迴圈。

case

執行pattern與expr結果相同行的指令。

case expr in
        pattern1) commands ;;
        pattern2) commands ;;
esac

cd

變更現行目錄。

continue

跳過迴圈的剩下部份,直接進行迴圈的判斷。

do

for,while或until迴圈的開頭。

done

for,while或until迴圈的結尾。

echo

將參數的部份顯示於輸出(有時是內建指令)。

esac

case指令的結尾。

eval

讓shell將eval後面接的參數當指令執行。

exec

將接於其後的指令直接於現行shell中執行,而不是在child process中執行。

exit n

離開shell script並傳回n。

export

將後面所接的參數傳進shell變成環境變數,而不會隨著shell結束而消失,在ksh和bash中export還可以用來設定變數。

false

(ksh/bash內建指令)在指令直接傳回false值。

fc

(ksh/bash)顯示/編輯已用過的指令表。

fg

(ksh/bash)讓背景程式回到前景中執行。

fi

if指令的結尾。

for

重覆執行一段程式碼。

for variable [ in list ]
do
        command
done

function

(ksh/bash)用來定義一段函數的關鍵字。

# 定義函數
function_name() {
  commands
}

# 呼叫函數
function_name

getopts

對指令列參數一一執行的函數。

history

(ksh/bash)秀出使用者最近執行過的指令。

if

條件判斷。

if test-command
then commands
[elif commands]
[else commands]
fi

integer

(ksh/bash)指定整數變數。

jobs

(ksh/bash)列出在背景中執行或暫停的行程。

kill

送signal給行程用的程式,通常用於中止process或將process重新啟動。

let

(ksh/bash)進行整數數學運算用。

newgrp

(ksh)變更目前所屬群組(變更有效的GID),影響新建的檔案或目錄。

print

(ksh)和echo的作用相同。

pwd

列出現行所在目錄。

r

(ksh)重新執行前一個指令。

read

從標準輸入讀入一行內容,並將內容存在其後的變數中,若字數大於變數,則其他的字將會被存在最後一個變數中。

readonly

表示變數是唯讀的。

return

從function傳回。

select

(ksh/bash)顯示一個可以讓使用者選擇的選單。

set

顯示或修改shell的各種選項。

shift

將所有的參數往前進一位,$1將被$2取代,原本的$1的內容將被拋棄。

test

(ksh/bash builtin)用來檢驗檔案、字串及數值用的指令,通常用[]來代替。

trap

用來補捉signal用,如以下signal:

0      exit from script
1      hangup/disconnect
2      intr key pressed(Ctrl-C or DEL)
3      quit key pressed
15    request to terminate process

type

顯示指令的完整路徑名稱(或顯示該指令為內建指令/別名)。

typeset

(ksh/bash)設定變數種類及其初始化值。

ulimit

顯示可用最大的檔案大小及其他資源上限。

umask

顯示/設定新增檔案或目錄時的預設檔案屬性。

unalias

(ksh/bash)移除別名。

unset

移除變數。

until

(ksh/bash)重覆執行,直到until後的判斷為真時才停止。

until test-command
do
        commands
done

wait

暫停執行,直到背景的程式都工作完畢。

whence

(ksh)類似type指令。

while

只要while後的判斷為真,則迴圈會不斷重覆執行。

while test-command
do
        commands
done

 

條件控制指令
條件控制指令可以用在以下三個地方:
if [ test-expression ]
while [ test-expression ]
until [ test-expression ]

檔案測試  

-a file

file存在則為真(ksh/bash才支援)。

-b file

file存在且為block類型檔案(以block為單位讀取的裝置)。

-c file

file存在且為character(字元裝置)類型檔案。

-d file

file存在且為目錄型態(UNIX下目錄也算檔案的一種)。

-e file

file存在則為真。

-f file

file存在且為一般檔案。

-g file

file存在且SGID bit已被設定(set gid)。

-G file

file存在且GID和使用者相同。

-k file

file存在且file的sticky bit被設定。

-L file

file存在且為鏈結(symbolic link)。

-O file

file存在且其擁有者為一有效使用者。

-p file

file存在且型態是name pipe。

-r file

file存在且可讀取。

-s file

file存在且大小不為0。

-S file

file存在且為socket。

-t filedes

file descriptor(檔案描述子)存在且為終端機設備。

-u file

file存在且SUID bit已被設定(set uid)。

-w file

file存在且可寫入。

-x file

file存在且可執行。

字串比對  

-z string

string為零長度字串。

-n string

string為非零長度字串。

s1 = s2

s1和s2內容相等。

s1 != s2

s1和s2內容不相等。

s1

s1為非零長度字串。

s1 < s2

(ksh/bash)s1在ASCII字元集的順序先於s2。

s1 > s2

(ksh/bash)s1在ASCII字元集的順序後於s2。

數值比對  

n1 -eq n2

n1與n2相等(equal)。

n1 -ne n2

n1與n2不相等(not equal)。

n1 -gt n2

n1大於n2(greater)。

n1 -ge n2

n1大於或等於n2(greater or equal)。

n1 -lt n2

n1小於n2(less than)。

n1 -le n2

n1小於或等於n2(less or equal)。

! expr

當expr不為真時,此行為真。

-a

邏輯的AND(Bourne)。

&&

邏輯的AND(bash/korn)。

-o

邏輯的OR(Bourne)。

||

邏輯的OR(bash/korn)。

 

數學運算指令(ksh/bash)
使用let指令指定運算:
let "VARIABLE=integer_expression"
若是在指令中直接使用 (( ))
$((integer_exprsssion))
也可使用expr來進行運算
expr $var1 + $var2

ksh/bash支援的運算子
.邏輯運算子傳回1是真,傳回0為假。
.以下優先順序為由高到低:

- 負號
!~ 邏輯的”否”
* / % 乘號,除號,取餘數
+ - 加號,減號
>> << bit運算元,右移與左移。
如:$((32 >> 2))答案是8,因為右移2個bit相當於除以4。
<= >= 小於等於,大於等於
> < 大於,小於
== != 等於,不等於
& bit運算元,將bit做AND運算。< br /> 如$((5 & 3))將會把5轉為2進位的101,3轉為011,做AND後答案是1。
^ bit運算元,XOR,兩個bit相同時為0,不同時為1。
| bit運算元,OR
&& 邏輯運算元,AND
|| 邏輯運算元,OR
*= += %= 和C中的運算元一樣,運算並指定。
如:$((a *= 2))表示a=a*2。將a值取出乘2後存回到a中。
= += -= 與上類似,加減後存回
>>= <<= 移位後存回
&= ^= |= 做AND,XOR,OR後存回

 

參數與變數

使用者自定變數  

USERVAER=value

將USERVAR指定value值。

$USERVAR

取出USERVAR值。

${USERVAR}

取出USERVAR值。加上{}避免混淆。

.使用者自定變數需以英文字母或底線(_)開頭。
.變數名稱只能由英文字母、數字或底線組成。
.通常使用全大寫名稱以便與UNIX指令區別。

ksh/bash 2.x支援陣列  

$USERVAR[index]=value

設定陣列元素值。

${USERVAR[index]}

取出陣列元素值。

${USERVAR[*]}

取出所有陣列元素值。

${USERVAR[@]}

取出所有陣列元素值,但各值以”分隔。

index必須是整數數字。

ksh陣列的初始化方法

set -A USERVAR value1 value2 value3 …

bash陣列的初始化方法

USERVAR=(value1 value2 value3 …)

 

內建shell變數  

$0

正在執行的shell script名稱或指令名。

$n

${n}

n介於1~9之間,代表第n個參數。

這樣就可以讀到${10}以上的參數值

$#

參數的總個數。

$*

所有參數的列表。

$@

所有參數的列表,各參數以”隔開。

$?

上個指令的傳回值。

$$

現在的shell的pid值。

$!

上一個背景指令的pid值。

會影響變數的內建指令
getopts,export,read,readonly,unset

變數的兩個種類  

環境變數

會傳給所有的子行程。

區域變數

不會傳給子行程。

 

Shell變數  

CDPATH

以:分開的各個目錄,cd指令會在這些目錄中搜尋是否有符合的目錄以變更現行目錄。

HOME

使用者登入的目錄。

HOSTNAME

機器的電腦名稱。

IFS

Internal field separator字元,用來區隔各欄位。

OPTARG

最後一個被getopts處理的參數。(ksh/bash)

OPTIND

最後一個被getopts處理的參數索引。(ksh/bash)

PATH

以:隔開的目錄,shell將在這些目錄中搜尋指定的執行檔。

PS1

shell的第一個提示符號。

PS2

shell的第二個提示符號,當指令無法一行打完時用。

PWD

現行目錄。

RANDOM

介於0到32767間的亂數,每次存取都不同。

REPLY

最後被select讀取的輸入行。

SECONDS

shell初始化到現在所經過的秒數。

SHLVL

目前的shell是巢狀呼叫中的第幾層。

UID

使用者的ID。

 

參數代換

sh/ksh/bash可用的代換  

${parameter}

用parameter的值代換,parameter可以是整數或變數名。

${parameter:-word}

若parameter的值是空(null)或未設定值,此時本行的值為word(parameter的值不變)。

${parameter:=word}

若parameter的值是空(null)或未設定值,此時parameter的值將被設為word。

${parameter:?message}

若parameter的值是空(null)或未設定值,此時message將會被印在標準錯誤輸出(standard error)上,通常用以檢查變數值是否被正確的設定。

${parameter:+word}

若parameter的值已被設定,此時本行的值為word(parameter的值不變),作用與${parameter:-word}相反。

ksh/bash才可用的代換  

${!prefix*}

會被展開為名稱從prefix開頭的變數一覽。展開時的區隔文字是使用變數IFS的第一個字。

${#parameter}

計算parameter的字元數。

${#array[*]}

計算陣列中有幾個值。

${parameter#pattern}

若parameter中有符合以正規表示式表達的pattern敘述的話,就將parameter的該部份刪去,但儘可能刪去符合pattern的最小部分。

${parameter##pattern}

與上面指令類似,儘可能刪去最大的範圍。

${parameter%pattern}

與上面指令類似,儘可能刪上由尾算來最小的範圍。

${parameter%%pattern}

與上面指令類似,儘可能刪上由尾算來最大的範圍。

${parameter:offset}

從parameter中取出offset以後的字元,offset正數從左邊數,負數從右邊數。

${parameter:offset:length}

從parameter中取出offset以後length長的字元

${parameter/pattern/string}

將parameter中的一個pattern取代成string

${parameter//pattern/string}

將parameter中的所有pattern取代成string

EX:
r="/usr/local/bin/sftp"
path=${r##*/}
path=sftp

在bash中,若在parameter的前面放上「!」的話,則會以變數parameter中的值當成變數名稱,來進行展開或相關的處理(${!prefix}除外)
EX:foo=bar
     bar=baz
     echo $(foo)
bar
     echo $(!foo)
baz

萬用字元比對
檔名比對原則:
.任何在指令列輸入的字串,若包含萬用字元則會與目錄中的檔名做比對並代換成檔名列表。
.若沒找到任何符合條件的檔名,則原字串不做代換。
.萬用字元無法與.或/開頭的檔案做比對。

可用的萬用字元(sh/ksh/bash)  

*

等於零或多個任意字元

?

等於一個任意字元

[字元]

等於在[]中的任何一個字元

[!字元]

不等於在[]中的任何一個字元

 

ksh才支援的萬用字元  

?(pattern1|pattern2…)

pattern中任一符合均可。

*(pattern1|pattern2…)

pattern中有0或多個符合均可。

+(pattern1|pattern2…)

pattern中有1或多個符合均可。

@(pattern1|pattern2…)

pattern中只唯一符合才可。

!(pattern1|pattern2…)

不符合任何一個pattern才可。

 

輸入/輸出(I/O)

UNIX的標準輸入輸出    
縮寫 種類 檔案符號

STDIN

標準輸入

0

STDOUT

標準輸出

1

STDERR

標準錯誤輸出

2

 

cmd > file

將標準輸出導入檔案。

cmd 1> file

與上同。

cmd >> file

將標準輸出附加到檔案之後。

cmd 1>> file

與上同。

cmd 2> file

將標準錯誤輸出導入檔案。

cmd 2>> file

將標準錯誤輸出附加到檔案之後。

cmd < file

由檔案中讀取內容當成標準輸入。

cmd 0< file

與上同。

Here Document:利用標籤印出一大段字串,而不必使用引號。可以讓許多列文字變成標準輸入,它會讀取若干列資料,直到遇到某一個標記為止。由鍵盤輸入資料的方法:
cmd << delimiter
one or more text lines
delimiter

cmd1 | cmd2

將cmd1的輸出當成cmd2的輸入。

cmd | tee file

將cmd的輸出同時送到標準輸出及file中。

exec n > file

將輸出到第n個檔案描述子(file descriptor)的輸出改成送到file去。

exec n >> file

與上同,但是是附加到file後。

cmd 2 >&1

將標準錯誤輸出導向到標準輸出去。這對於需要將錯誤訊息及輸出同時送給另個程式處理時很方便。

如:cmd > file 2>&1,須注意是 2>&1必須放到 > file之後。

cmd >&2

將標準輸出導向到標準錯誤輸出。

cmd 1>&2

與上同。

cmd n>&m

將第n個檔案描述子到第m個檔案描述子去。

exec n>&-

關閉第n個檔案描述子。

 

其他指令總結

以下是一些shell script中常用的指令

echo

顯示參數到輸出上。

\b:倒回鍵
\c:讓echo在行末不會換行
\f:Formfeed
\n:換行
\r:歸位(跳回一行開頭)
\t:Tab
\\:反斜線(\)
\0nn:以八進位表示的ASCII值

grep

顯示出符合條件的行

-i:條件設定成大小寫皆吻合
-l:只列出符合條件的檔名,而不列出該行
-n:列出符合條件的行時同時顯示行號
-v:測試用,將會忽略符合條件的行

printf

顯示格式化字串

printf “text %[-]m.nx” arguments

-:對齊左邊(選用)
m:欄位最小長度
n:欄位最大長度,若欄位是數字時表示顯示到小數點後幾位
x:參數的種類。
        s:字串
        c:字元
        d:十進位整數
        x:十六進位整數
        o:八進位整數
        e:指數表示的浮點數
        f:固定長度浮點數(fixed floating point value)
        g:一般浮點數(general floating point value)

sort

將各行依條件排序

-b:忽略各行開頭的空白字元。
-d:忽略各行開頭的標點符號。
-f:將大小寫字元排在一起。
-n:將數字當成數值來比對,而不是以ASCII的順序。
-r:反向排序。
+n:從第n個欄位開始排序。

 

正規表示式萬用字元(Regular Expression Wildcards)

grep、fgrep、egrep、sed、vi、perl及awk中可以使用萬用字元來當做要搜尋的樣本。

正規表示式萬用字元的限制

^pattern

以pattern開頭的行。

pattern$

以pattern結尾的行。

.

代表一個任意字元。

[list]

代表list中的任意一個字元。

[^list]

代表除了list中的任意一個字元。

*

代表零或多個在*之前的字元。

.*

代表零或多個任意字元。

[:class:]

表示與文字類別class指定的種類符合的文字。使用時是寫在「[…]」(文字類別的指定)裡面(例:「[[:alpha:]]」)。關於類別名稱請參照別表。

\(regexp\)

將正規表示regexp當成一整個群組來看待(例:「\(word\)*」會與「wordword」等符合)。另外,若有字串與「\(」…「\)」內的正規表示符合的話,之後可用「\1」來參照之(例如:「\(…\)\1」會和「abc abc」「xyz xyz」等符合)。若有多個「\(」…「\)」的話,第2次之後可用「\2」「\3」…「\9」來參照之(最多到9個)。

正規表示式萬用字元的支援

{\n\}

代表前一元素出現n次

\{n,\}

代表前一元素出現的次數大於n次

\{n,m\}

代表前一元素出現的次數大於n次而小於m次

?

代表前一個元素出現0或1次。

+

代表前一個元素出現1次以上。

 

BRE/ERE的文字類別(POSIX字元組) ASCII環境 Unicode環境

[:alnum:]

英文字與數字(10進位)

[a-zA-Z0-9]

[\p{L&}\p{Nd}]

[:alpha:]

英文字

[a-zA-Z]

\p{L&}

[:ascii:]

ASCII字元

[\x00-\x7F]

\p{InBasicLatin}

[:blank:]

空白(空白字元或縮排)

[ \t]

[\p{Zs}\t]

[:cntrl:]

控制文字(控制碼)

[\x00-\x1F\x7F]

\p{Cc}

[:digit:]

10進位數字

[0-9]

\p{Nd}

[:graph:]

可印出且可顯示的文字(即非控制碼亦非空白字元)

[^ \t\n\r\f\v]

[^\p{Z}\p{C}]

[:lower:]

小寫英文字

[a-z]

\p{Ll}

[:print:]

可印出的字元(控制碼以外的字元)

[^\t\n\r\f\v]

\P{C}

[:punct:]

標點符號

[][!"#$%&'()*+,./:;<=>?@\^_`{|}~-]

[\p{P}\p{S}]

[:space:]

空白字元、縮排、換頁

[ \t\n\r\f\v]

[\p{Z}\t\r\n\v\f]

[:upper:]

大寫英文字

[A-Z]

\p{Lu}

[:word:]

字母字元

[A-Za-z0-9_]

[\p{L}\p{N}\p{Pc}]

[:xdigit:]

16進位數字

[A-Fa-f0-9]

[A-Fa-f0-9]

 

BRE的符號一覽

[:class:]

表示與文字類別class指定的種類符合的文字。使用時是寫在「[…]」(文字類別的指定)裡面(例:「[[:alpha:]]」)。關於類別名稱請參照列表。

[chars…]

文字類別的指定。表示chars…中的任一個文字。若chars…的第一個文字是「^」的話,則是表示不含在chars…中的任一文字。

\(regexp\)

將正規表示regexp當成一整個群組來看待(例:「\(word\)*」會與「wordword」等符合)。另外,若有字串與「\(」…「\)」內的正規表示符合的話,之後可用「\1」來參照之(例如:「\(…\)\1」會和「abc abc」「xyz xyz」等符合)。若有多個「\(」…「\)」的話,第2次之後可用「\2」「\3」…「\9」來參照之(最多到9個)。

*

把前面的正規表示重複0次以上。

\{n,m\}

把前面的正規表示重複n次以上,m次以下

\{n\}

把前面的正規表示剛好重複n次

\{n,\}

把前面的正規表示重複n次以上

^

表示字串的開頭,或是行的前頭。

$

表示字串的末尾,或是行的最後。

.

表示任一個文字。

 

ERE的符號一覽

[:class:]

表示與文字類別class指定的種類符合的文字。使用時需寫在「[…]」(文字類別的指定)裡面(例:「[[:alpha:]]」)。類別名稱與BRE同。

[chars…]

文字類別的指定。表示chars…中的任一個文字。若chars…的第一個文字是「^」的話,則是表示不含在chars…中的任一文字。

(regexp)

將正規表示regexp當成一整個群組來看待(例:「\(word\)*」會與「wordword」等符合)。

*

把前面的正規表示重複0次以上。

+

把前面的正規表示重複1次以上。

?

把前面的正規表示重複0次或1次。

{n,m}

把前面的正規表示重複n次以上,m次以下

{n}

把前面的正規表示剛好重複n次

{n,}

把前面的正規表示重複n次以上

^

表示字串的開頭,或是行的前頭。

$

表示字串的末尾,或是行的最後。

|

表示前後任一個正規表示。

.

表示任一個文字。

 

正規表示式的脫逸字元

\a

警告音(BEEP)

\b

Backspace

\n

換行

\r

return(換行)

\f

換頁

\t

縮排

\octal

以2~3位數的8進位數octal來表示的文字

\xhex

以2位數的16進位數hex來表示的文字

慢慢補全囉!哈!


調查使用「|」來連結的各指令的終止碼
${PIPESTATUS[n]}
n從0開始


將變數的內容當成指令來執行
eval [arg]


使用subshell來執行
( command [; command …] )
用「(…)」括起來的指令,會在subshell中被執行。
若我們在subshell中變更了變數的內容或目前資料夾的位置,在subshell結束之後,還是會回到原來的值。
Subshell在文法上會被看成是一個指令,因此我們可以把它全體做重新導向,或是使其在背景執行。
( make && make install ) &


使用grouping({…})來執行
{ command [; command ..]; }
用「{…}」括起來的指令,會被當成同一個群集來執行(grouping)。
與subshell一樣,文法上會被看成是一個指令,因此我們可以對它做重新導向,或是使其在背景執行。
{ make && make install; } &
{ cat first; cat second; } >third


一些 man page 沒提到的 --date=STRING 使用方法
date -d "yesterday" # 顯示昨天的時間
date -d "tomorrow" # 顯示明天的時間
date -d "1 hour" # 顯示一小時後的時間
date -d "2 day ago" # 顯示二天前的時間
date -d "3 month ago" # 顯示三個月前的時間
date -d "2 year" # 顯示二年後的時間
date -d "last friday" # 顯示上個星期五的時間
date -d "next week" # 顯示下週的時間
date -d "next month" # 顯示下個月的時間
date -d "fortnight" # 顯示二週後的時間
date -d "7/1 3 week" # 顯示 7/1 起算的第三週
date -d "20250615 yesterday" +%Y%m%d #顯示某天的前一天,格式用 yyyymmdd

tomorrow:
date --date="tomorrow"
date --date="1 day"
yesterday:
date --date="yesterday"
date --date="1 day ago"
in X days:
date --date="X days"
X days ago:
date --date="X days ago"
date --date="-X days"


取出字串的第n個單字
set -- string
EX:text=’Your nature demands love and your happiness depends on it.’
    set -- $text
    echo “Number of words: $#”
    echo “The fourth word: $4”


將字串用指定的區隔文字來做分割
IFS=’separators’ ; set – string
EX:_IFS=”$IFS”    # 先把IFS的內容存起來
    IFS=”,”        # 將區隔文字設為「,」
    Set -- $text    # 分割結果會被放到$1,…$9內
    IFS=”$_IFS”    # 將IFS的內容復原


傳回 var 變數值的字元數。
${#var}


只抽取出重複的行
uniq -d [filename]


將重複的行刪除
uniq -u filename


取hostname的host,不要domain:
HOST=`hostname`
HOST=${HOST%%\.*}


增量備份的實務應用
假設欲對系統目錄 /root/docs/ 目錄做每日備份工作時,3月1日為第一次備份日期,則將該目錄所有檔案壓縮為backup-0301.tar.gz,3月2日則只需備份有變動的檔案為backup-0302.tar.gz。
1. 初次備份(3月1日)的指令
#tar備份目錄所有檔案
# tar cvfz backup-0301.tar.gz /root/docs/*
#備份完成後,立即產生一個「時間參考檔」
# touch /root/docs/timebase
2. 增量備份
#使用find指令搜尋出在「時間參考檔」之後變動的檔案名稱,再利用tar指令備份這些檔案
# tar cvfz backup-0302.tar.gz `find /root/docs/ -cnewer`
#更動「時間參考檔」做為下次備份的基準
# touch /root/docs/timebase


20250615

上一篇: 照顧老貓腸胃,貓貓益生菌推薦,從敏感體質到穩定日常 下一篇: 《開創心態》試讀心得——不是一種才華,而是一種選擇

網站公告:

用戶註冊時,上傳的內容需為原創或已獲授權,如若被侵權,請連繫平台管理者,且平台會盡速移除下架該內容。

聯絡我們

信箱:zonchits@gmail.com