Markdown

[bash]bash 筆記

Shell

#!/bin/bash
#

:<<BLOCK
BLOCK

#!/usr/bin/ruby

:<<BLOCK

REGEX

\ 跳脫字元
^
$
*等價於{0,} 匹配前面的紫表達式任意次 zo* z zo zoo
+ 匹配>=1次 zo+ zo zoo 等價 {1,}
? 匹配0次或1次 do(es)? do does 等價{0,1}
{n} 匹配n次 o{2} food
{n,} 至少匹配n次
{n,m} 匹配最少n次最多m次
? 非貪婪
. 匹配除"\r\n" 之外的所有字符, 若要匹配包含"\r\n" 在內的所有字符,請用 "[\s\S]"
()
x|y z|food z,food,zood;  (z|f)ood zood,food


BLOCK



Shell 特殊符號

" => 用來使 shell 無法辨識出字符 $ ` \ 以外的任何字符或字串,又稱為弱引用
’ => 用來使 shell 無法辨識出所有特殊字符,也稱之為強引用
` => 將當前命令優先執行
; => 允許在一行上放多個命令
& => 背景執行,通常會加上 nohup
{} => 建立命令區塊
<>& => 重新定向
*? []! 模式匹配
$ 變數開頭
# 表示注釋(第一行除外)

變數與運算符號

變數名稱="變數"
readonly 變數名稱=“變數” 不能被改變
echo $變數名稱
set 顯示本地所有變數
unset 變數名稱清除變數值
readonly 顯示當前 shell 下唯讀變數
變數設定在
$HOME/.bash_porfile(/etc/porfile)
設定環境變數
export test=“123”
查看
env、export
#!/bin/bash

# shell 支援的位置變數有10個,超過要用其他方法表示
echo "第一個變數: $0"
echo "第十個變數: $9"

echo "第十一個變數: ${10}"
特殊變數$* $@ 表示所有的位置參數
$#表示位置參數的總數
bash -x 可以拿來測試 shell 會印出每一行,在印出每一行的執行結果
如果只想測試某幾段的話可以使用
set -x
測試段落
set +x
來測試

一個UNIX PROCESS或命令終止時,將會向父進程返回一個 exit 狀態,
若該進程成功執行完畢,則會返回一個數值為0的出口狀態,異常則非0。
在 Shell 中,可以用 exit[n] 來指定返回的exit 狀態,其中 n=0~255
eric@ubuntu:~/script$ cat test.sh 
#!/bin/bash

echo "first paramater: ${10}"

echo $PWD #當前目錄
echo $RANDOM #每次引用會隨機產生0~32767的值
echo $SCONDS #腳本已運行秒數
echo $PPID #當前進程的父進程ID
echo $? #最近一次執行的命令或 shell 腳本的exit狀態

echo $EDITOR
echo $HOME
echo $PATH
eric@ubuntu:~/script$ ./test.sh 
first paramater: 
/home/eric/script
24326

13585
0

/home/eric
/home/eric/.nvm/versions/node/v8.11.3/bin:/home/eric/bin:/home/eric/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

shell 中並未嚴謹區分變數的類型,但可以使用 typeset、declare 定義變數的類型,並在定義的同時進行初始化。
declare -A dict

dict=([key1]="value1" [key2]="value2" [key3]="value3")

for d in ${dict[@]}
do
    echo $d
done


eric@ubuntu:~/script$ ./test.sh 
value3
value2
value1


常用命令

:<<BLOCK
冒號(:) 與 true 語句不執行任何實際的處理動作,但可以用於返回一個 exit 0 的測試條件

while :
搭配 sleep 可實現秒級別的 cron 任務

while :
do
 ...
 sleep 1
done

---

echo、print 常與 awk 搭配


BLOCK
#!/bin/bash
echo -n "Enter your name: "
read name
echo "hello $name, welcome!"

# 使用 -p 可以直接在 read 中提示輸入,省去一行
read -p "Enter your name: " name
echo "hello $name, welcome!"

exit 0

set、unset

# set 用於修改或重新設定位置參數的值,不太任何參數時輸出所有內部變數

set -- #用於清除所有位置參數

a=34
unset a # 用於清除變數,將變數設為 null

expr

exp1+exp2
exp1-exp2
exp1/*exp2
exp1/exp2
exp1%exp2

#compare string
str1=str2
#will return boolean

命令替換

#!/bin/bash
today=$(date)
echo $today

unset today

today=`date`
echo $today

test 語句

test + if/then + case 組成shell的控制轉移結構
test expression # if ture return exit 0 else return exit num

[ expression ] #需要空格
[[expression]]

文件測試運算符

用於測試文件的狀態和屬性。
-e file # if exist
-r file # exist && readable
-w file # exist && writeable
-x file # exist && excuteable
-s file # exist && size >0
-f file # exist && is a normal file
-d file # exist && is a dir
-L file # exist && is a link file
-c file # exist && 字符特殊文件
-b file # exist && 塊特殊文件
-p file # exist && pipe 文件

常用舉例:
BACKDIR=/data/backup
[ -d ${BACKDIR} ] || mkdir -p ${BACKDIR}
[ -d ${BACKDIR}/${DATE} ] || mkdir ${BACKDIR}/${DATE}
[ ! -d ${BACKDIR}/${OLDDATE} ] || rm -rf ${BACKDIR}/${OLDDATE}
字符測試運算符
-z str # if the length of string is 0 return true
-n "str" # if the length of string is not 0 return true
s1=s2 #
s1!=s2
s1<s2

if[[ "$a"<"$b" ]]
if[[ "$a"/<"$b" ]]
整數測試運算符
# test 中的整數值比較會採用 c 的 atoi() 將字符轉換成等價的ASC,所以可以用數字字串跟整數比較

-eq # =
-ne # !=
-gt # >
-lt # <
-ge # >=
-le # <=
邏輯運算符
(expression) # 用於計算括號中的組合表達式,若結果為真回傳真
!exp # 可針對表達式進行邏輯非運算,即對測試結果求反,例如: test! -f file1
-a 、 &&
-o 、 ||

cmd1 && cmd2
cmd1 && cmd2

自訂 function

#!/bin/bash :<<BLOCK function name() { action; [return 數值;] } # return 值 0~255 如果不加,將以最後一條命令的執行結果當作返回值 BLOCK function traverse(){ for file in `ls $1` do if [ -d $1"/"$file ] then traverse $1"/"$file else echo $1"/"$file fi done } traverse "${PWD}"

字串擷取


#!/bin/bash


#shell 中的字串擷取

#第一種

varible=hello

echo "varible = ${varible}"

string=h

#   #、% : 控制方向,#由左至右,%由右至左,一個代表取締一個,兩個代表曲最後一個

echo ${varible##*${string}} #ello 由左向右擷取最後一個string 後的字串

string=l
echo ${varible#*${string}} #lo 從左向右擷取第一個string後的字串

echo ${varible%%${string}*} #he 由右至左曲最後一個string後的字串

echo ${varible%${string}*} #hel 由右向左曲第一個string後的字串



#第二種,直接設定開始結束位置
echo '--- method 2 ---'
echo ${varible:0:2} # he


echo `ls -al |cut -d "." -f2`

Array

#!/bin/bash

:<<BLOCK
#define

array_name=(value0 value1 value2 value3)

array_name=(
value0
value1
value2
value3
)

array_name[0]=value0
array_name[1]=value1
array_name[2]=value2


#read
#${array_name[index]}
value=${array_name[2]}
BLOCK

name=(
aaa
bbb
ccc
ddd
)

# read by index
echo "first index: ${name[0]}"
echo "second index: ${name[1]}"

# read all
echo "${name[*]}"
echo "${name[@]}"

# get array length

length=${#array_name[@]}
length=${#array_name[*]}

字典檔(key-value pair)

#!/bin/bash

# 一定要先宣告,在進行定義
declare -A dic
dic=([key1]="value1" [key2]="value2" [key3]="value3")

#print value of key
echo ${dic[key3]}

#print all keys
echo ${!dic[*]}

#print all values
echo ${dic[*]}

#print all key value

for key in $(echo ${!dic[*]})
do
echo "$key : ${dic[$key]}"
done

shell 中的控制結構

if
then
...
else
...
fi

---

if [[ a -eq b ]]
then
...
elseif [[ a -le b ]]
then
...
else
...
fi

#!/bin/bash

if [ "10" -lt "12" ]
then
    echo "10 < 12"
else
    echo "10 > 12"
fi
case
case value in
1)
command1
;;
2)
command2
;;
*)
command3
esac


sed

awk

grep

留言