Shell中經(jīng)常遇到一些符號(hào)容易混淆直秆,今天一起總結(jié)學(xué)習(xí)下加深理解。
1. $()
和 ``
$()
與`` (反引號(hào)) 都是用來(lái)做命令替換用的鞭盟。
我們直接看例子:
=> echo 5加4等于:$(expr 5 + 4)
5加4等于:9
=> echo 5加4等于:`expr 5 + 4`
5加4等于:9
在操作上圾结,這兩者都是達(dá)到相同的效果,但是建議使用$()
齿诉,理由如下:
在多層次的復(fù)合替換中筝野,`` 必須要轉(zhuǎn)義處理(反斜線),而$()
比較直觀粤剧。如下例子(只是為了說(shuō)明多層次命令歇竟,不用介意具體運(yùn)算):
=> echo 5加4加1等于:$(expr $(expr 5 + 4 ) + 1)
5加4加1等于:10
=> echo 5加4加1等于:`expr \`expr 5 + 4\` + 1`
5加4加1等于:10
2. ${}
:變量替換
${}
用于變量替換。一般情況下抵恋,$var
與${var}
結(jié)果差不多焕议。但是用 ${}
會(huì)精確的界定變量名稱的范圍。例子:
=> file="test";echo $file_txt
#空值弧关,因?yàn)闆](méi)有定義file_txt
=> file="test";echo ${file}_txt
test_txt
${}
的一些其他功能:
1)${}
信息提取
主要有以下四種, 此部分內(nèi)容參考學(xué)習(xí)(Linux shell 之 提取文件名和目錄名的一些方法):
我們以var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
為例說(shuō)明
A. ${var##*.}
:該命令的作用是去掉變量var從左邊算起的最后一個(gè)'.'字符及其左邊的內(nèi)容盅安,返回從左邊算起的最后一個(gè)'.'(不含該字符)的右邊的內(nèi)容。結(jié)果如下:
=> var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
=> echo ${var##*.}
gz
因此使用該命令世囊,可以提取出我們需要的文件后綴别瞭。
B、${var#*.}
: 該命令的作用是去掉變量var從左邊算起的第一個(gè)'.'字符及其左邊的內(nèi)容株憾,返回從左邊算起第一個(gè)'.'(不含該字符)的右邊部分的內(nèi)容畜隶。例子結(jié)果如下:
=> var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
=> echo ${var#*.}
fq.gz
使用該命令,可以提取出文件的多個(gè)后綴号胚。
C籽慢、${var%/*}
: 該命令的使用是去掉變量var從右邊算起的第一個(gè)'/'字符及其右邊的內(nèi)容,返回從右邊算起的第一個(gè)'/'(不含該字符)的左邊的內(nèi)容猫胁。例子結(jié)果如下:
=> var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
=> echo ${var%/*}
/home/test/dir1/dir2
從結(jié)果可看出箱亿,使用該命令,可以提取出需要的文件所在的目錄弃秆。
D届惋、${var%%.*}
: 該命令的使用是去掉變量var從右邊算起的最后一個(gè)'.'字符及其右邊的內(nèi)容髓帽,返回從右邊算起的最后一個(gè)'.'(不含該字符)的左邊的內(nèi)容。使用例子及結(jié)果如下:
=> var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
=> echo ${var%%.*}
/home/test/dir1/dir2/V3_L01_99_2
使用該命令脑豹,可以提取出需要的文件除去多個(gè)后綴后的路徑與文件名郑藏。
從這也可發(fā)現(xiàn)一些規(guī)律,即:
#:表示從左邊算起第一個(gè)
##:表示從左邊算起最后一個(gè)
%:表示從右邊算起第一個(gè)
%%:表示從右邊算起最后一個(gè)
當(dāng)然上述操作的作用并不只是為了提取文件名或后綴瘩欺,只是為了說(shuō)明${}
在信息提取上的應(yīng)用必盖;shell中文件名或后綴的提取可直接使用basename和dirname,還是以上述為例:
=> var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
=> echo $(basename $var)
V3_L01_99_2.fq.gz
=> echo $(basename $var .fq.gz)
V3_L01_99_2
=> echo $(dirname $var)
/home/test/dir1/dir2
2)${}
substring 按字符位置俱饿、長(zhǎng)度截取
格式:${var:offset:length}
,取得字符串的子字符串
直接看例子:
var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
echo ${var:0:5} #從頭開始歌粥,提取最左邊的 5 個(gè)字節(jié),結(jié)果:/home
echo ${var:5} #從提取第 5 個(gè)字節(jié)右邊到結(jié)尾的字符拍埠,結(jié)果:/test/dir1/dir2/V3_L01_99_2.fq.gz
echo ${var:5:5} #提取第 5 個(gè)字節(jié)右邊的連續(xù) 5 個(gè)字節(jié)失驶,結(jié)果;/test
echo ${#var} #計(jì)算出字符串的長(zhǎng)度枣购,結(jié)果:38
echo ${var: -5} #注意區(qū)分嬉探,中間有空格,提取最后五個(gè)字符棉圈,結(jié)果:fq.gz
echo ${var:-5} #結(jié)果:/home/test/dir1/dir2/V3_L01_99_2.fq.gz,為啥值等于$var涩堤,下面部分有解釋
echo ${var:(-5)} #注意上面三者的區(qū)分,結(jié)果:fq.gz
3)${}
查找替換和刪除
此部分參考學(xué)習(xí):bash字符串處理
- 查找替換:
${var/pattern/replacement}
:查找var變量存儲(chǔ)的字符中第一次由pattern匹配到的內(nèi)容迄损,并替換為replacement定躏;
${var//pattern/replacement}
:查找var變量存儲(chǔ)的字符中所有能夠由pattern匹配到的內(nèi)容,并替換為replacement芹敌;
例子:
=> var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz;echo ${var/dir/path}
/home/test/path1/dir2/V3_L01_99_2.fq.gz
=> var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz;echo ${var//dir/path}
/home/test/path1/path2/V3_L01_99_2.fq.gz
- 查找刪除:
${var/pattern}
:查找var變量存儲(chǔ)的字符中第一次由pattern匹配到的內(nèi)容痊远,并刪除;
${var//pattern}
:查找var變量存儲(chǔ)的字符中所有能夠由pattern匹配到的內(nèi)容氏捞,并刪除碧聪;
${var/#pattern}
:查找var變量存儲(chǔ)的字符中最開始處能夠由pattern匹配到的內(nèi)容,并刪除液茎;
${var/%pattern}
:查找var變量存儲(chǔ)的字符中最后位置能夠由pattern匹配到的內(nèi)容逞姿,并刪除;
例子如下:
=> var=home/test/dir1/home2/dir2/home;echo ${var/home}
/test/dir1/home2/dir2/home
=> var=home/test/dir1/home2/dir2/home;echo ${var//home}
/test/dir1/2/dir2/
=> var=home/test/dir1/home2/dir2/home;echo ${var/#home}
/test/dir1/home2/dir2/home
=> var=home/test/dir1/home2/dir2/home;echo ${var/%home}
home/test/dir1/home2/dir2/
4)${}
大小寫替換
^
替換為大寫捆等,^^
統(tǒng)統(tǒng)替換為大寫
,
替換為小寫滞造,,,
統(tǒng)統(tǒng)替換為小寫
var="home/test/dir1/dir2/V3_L01_99_2.fq.gz"
echo ${var^} # Home/test/dir1/dir2/V3_L01_99_2.fq.gz
echo ${var^^} # HOME/TEST/DIR1/DIR2/V3_L01_99_2.FQ.GZ
echo ${var,} # home/test/dir1/dir2/V3_L01_99_2.fq.gz
echo ${var,,} # home/test/dir1/dir2/v3_l01_99_2.fq.gz
5)利用 ${}
還可針對(duì)不同的變量狀態(tài)賦值(初始化、空值栋烤、非空值)
本部分參考學(xué)習(xí)https://blog.csdn.net/x1269778817/article/details/46535729
這也是上部分
${var:-5}
結(jié)果為啥還是等于$var的原因谒养。
6) ${}
數(shù)組與關(guān)聯(lián)數(shù)組
shell中的數(shù)組與關(guān)聯(lián)數(shù)組
聲明數(shù)組: declare -a array
聲明關(guān)聯(lián)數(shù)組: declare -A MAP
declare -a ARY #聲明數(shù)組
declare -A MAP #聲明關(guān)聯(lián)數(shù)組
MAP=([a]=1 [b]=2 [cde]=3 [f]=F) #關(guān)聯(lián)數(shù)組MAP
ARY=(a b cde f) #數(shù)組ARY
echo ${ARY[2]} #數(shù)組ARY,從0開始明郭,因此是第三個(gè)元素买窟,cde
echo ${#ARY[2]} #數(shù)組ARY丰泊,第三個(gè)元素的長(zhǎng)度, 3
echo ${ARY[@]} #數(shù)組所有元素, a b cde f
echo ${ARY[*]} #數(shù)組所有元素, a b cde f
echo ${#ARY[@]} #數(shù)組大小, 4
echo ${ARY[@]:0:2} #數(shù)組從頭開始前兩個(gè)元素,a b
echo ${ARY[@]: -2:2} #注意-2前面有空格始绍,原因上面講過(guò)瞳购,從最后一個(gè)元素-1開始向左數(shù)2個(gè)元素,cde f
echo ${MAP[@]} #關(guān)聯(lián)數(shù)組所有值亏推,1 3 2 F
echo ${#MAP[@]} #關(guān)聯(lián)數(shù)組大小学赛,4
echo ${MAP[cde]} #關(guān)聯(lián)數(shù)組cde的值,3
echo ${!MAP[@]} #返回索引径簿,a cde b f
3. $[]
與$(())
進(jìn)行數(shù)學(xué)運(yùn)算罢屈。支持+ - * / %:分別為 “加嘀韧、減篇亭、乘、除锄贷、求余"译蒂,如下:
a=10;b=8;c=5;
echo $a + $b #輸出:10 + 8
echo $(( a + b*c)) #輸出:50
echo $(((a*b)/c)) #輸出:16
#在 $(( )) 中的變量名稱,其前面可以加 $ 符號(hào)谊却,也可以不用柔昼,如:
echo $(( $a + $b * $c)) # 輸出也是 50
$[]
是 $(())
的過(guò)去形式,現(xiàn)在已經(jīng)不建議使用
4. []
即為test命令的另一種形式炎辨。
但要注意:
1).必須在左括號(hào)的右側(cè)和右括號(hào)的左側(cè)各加一個(gè)空格捕透,否則會(huì)報(bào)錯(cuò)。
2).test命令使用標(biāo)準(zhǔn)的數(shù)學(xué)比較符號(hào)來(lái)表示字符串的比較碴萧,而用文本符號(hào)來(lái)表示數(shù)值的比較乙嘀。
3).字符比較的大于符號(hào)或小于符號(hào)必須要轉(zhuǎn)義,否則會(huì)被理解成重定向破喻。
4). []
中的邏輯與和邏輯或使用-a 和-o 表示
例子:
num=10
str1=abc
#字符串
if [ $str1 = "abc" ];then
echo "this is $str1"
fi
# 輸出:this is abc
# 數(shù)字
if [ $num -gt 1 -a $num -lt 20 ];then
echo "this is $num"
fi
# 輸出:this is 10
if [ $num -gt 1 ] && [ $num -lt 20 ];then
echo "this is $num"
fi
# 輸出:this is 10
[]
條件判斷的一些總結(jié)虎谢,此部分參考來(lái)源全網(wǎng)最全的 bash 速查表 ;
statement1 && statement2 # and 操作符
statement1 || statement2 # or 操作符
exp1 -a exp2 # exp1 和 exp2 同時(shí)為真時(shí)返回真(POSIX XSI擴(kuò)展)
exp1 -o exp2 # exp1 和 exp2 有一個(gè)為真就返回真(POSIX XSI擴(kuò)展)
( expression ) # 如果 expression 為真時(shí)返回真,輸入注意括號(hào)前反斜桿
! expression # 如果 expression 為假那返回真
str1 = str2 # 判斷字符串相等曹质,如 [ "$x" = "$y" ] && echo yes
str1 != str2 # 判斷字符串不等婴噩,如 [ "$x" != "$y" ] && echo yes
str1 < str2 # 字符串小于,如 [ "$x" \< "$y" ] && echo yes
str2 > str2 # 字符串大于羽德,注意 < 或 > 是字面量几莽,輸入時(shí)要加反斜桿
-n str1 # 判斷字符串不為空(長(zhǎng)度大于零)
-z str1 # 判斷字符串為空(長(zhǎng)度等于零)
-a file # 判斷文件存在,如 [ -a /tmp/abc ] && echo "exists"
-d file # 判斷文件存在宅静,且該文件是一個(gè)目錄
-e file # 判斷文件存在章蚣,和 -a 等價(jià)
-f file # 判斷文件存在,且該文件是一個(gè)普通文件(非目錄等)
-r file # 判斷文件存在坏为,且可讀
-s file # 判斷文件存在究驴,且尺寸大于0
-w file # 判斷文件存在镊绪,且可寫
-x file # 判斷文件存在,且執(zhí)行
-N file # 文件上次修改過(guò)后還沒(méi)有讀取過(guò)
-O file # 文件存在且屬于當(dāng)前用戶
-G file # 文件存在且匹配你的用戶組
file1 -nt file2 # 文件1 比 文件2 新
file1 -ot file2 # 文件1 比 文件2 舊
num1 -eq num2 # 數(shù)字判斷:num1 == num2
num1 -ne num2 # 數(shù)字判斷:num1 != num2
num1 -lt num2 # 數(shù)字判斷:num1 < num2
num1 -le num2 # 數(shù)字判斷:num1 <= num2
num1 -gt num2 # 數(shù)字判斷:num1 > num2
num1 -ge num2 # 數(shù)字判斷:num1 >= num2
5. (())
及[[]]
(())
和[[]]
分別是針對(duì)數(shù)學(xué)比較表達(dá)式和字符串表達(dá)式的加強(qiáng)版洒忧。
可參考:Bash test and comparison functions
-
[[ ]]
結(jié)構(gòu)比[ ]
結(jié)構(gòu)更加通用 -
[[ ]]
支持字符串的模式匹配蝴韭,使用=~操作符時(shí)甚至支持shell的正則表達(dá)式。
繼續(xù)上面例子:
num=10
str1=abc
if [[ $num -gt 1 && $num -lt 20 ]];then
echo "this is $num"
fi
# 輸出:this is 10熙侍,注意寫成[ $num -gt 1 && $num -lt 20 ]會(huì)出錯(cuò)榄鉴;
if [[ $str1 =~ ab ]];then
echo "this is $str1"
fi
# 輸出:this is abc
(( ))
相比()
,不需要再將表達(dá)式里面的大小于符號(hào)轉(zhuǎn)義蛉抓,除了可以使用標(biāo)準(zhǔn)的數(shù)學(xué)運(yùn)算符外庆尘,還增加了自增自減等符號(hào);如
for ((i = 0; i < 10; i++)); do echo $i; done
# 輸出0-9的數(shù)
其他功能巷送,如{n..m} 代表n-m之間的數(shù)字驶忌,如{0..4}
和$(seq 0 4)
表示相同意思。/{,s}bin/表示/bin/和/sbin/笑跛,ab{c,d,e}表示abc付魔、abd、abe飞蹂,如實(shí)現(xiàn)文件的快速備份:cp run.sh{,.bak}几苍。
當(dāng)然隨時(shí)可查看bash 速查表