《Linux命令行與shell腳本編程大全》學習筆記

第 1 章 初識 Linux shell

win+s 輸入cmd檢查python是否安裝成功柑船, 或者win+s 喻频,輸入IDLE也可以使用python(IDLE是Python自帶的)橄浓。

python文本編輯器:Geany,subline text,vs code ,pycharm甚垦,jupyter notebook。但是Geany涣雕,subline text在配置上很容易出現(xiàn)問題艰亮,不建議使用。

在vs code中運行.py文件

打開vs code——新建文件——文件另存為——某文件夾——保存類型選成:Python——在文件中輸入print("Hello world! My name is Shuntai Yu.")——調(diào)試——啟動調(diào)試——python file

在cmd中運行.py文件

cd 到.py文件所在位置——輸入.py文件名——enter

給變量取名字是一件痛苦的事情胞谭,習慣于一些變量名字更是如此垃杖,以下是我常用的變量名:
id、tmp丈屹、foo调俘、goo、bar旺垒、arg彩库、fib、funct

第 1 章 初識 Linux shell

Centos基于Red Hat

第 3 章 基本的 bash shell 命令

默認bash shell提示符是美元符號($)先蒋,這個符號表明shell在等待用戶輸入骇钦,shell提示符并非一成不變。你可根據(jù)自己的需要改變它竞漾。
絕對文件路徑總是以正斜線(/)作為起始眯搭,指明虛擬文件系統(tǒng)的根目錄窥翩。

ls -F  #會在可執(zhí)行文件(比如上面的my_script文件)的后面加個星號,以便用戶找出可在系統(tǒng)上運行的文件鳞仙。
ls -a  #把隱藏文件和普通文件及目錄一起顯示出來
ls -R  #列出了當前目錄下包含的子目錄中的文件
ls -l

問號(?)代表一個字符寇蚊; 星號(*)代表零個或多個字符。

ls -l my_scr?pt 
ls -l my* 
ls -l my_s*t 
ls -l my_scr[ai]pt 
ls -l f[a-i]ll  #指 定字符范圍
ls -l f[!a]ll  #感嘆號(!)將不需要的內(nèi)容排除在外棍好。 

cp -i test_one  test_two   #好是加上-i選項仗岸,強制shell詢問是否需要覆蓋已有文件。 
cp -i test_one  Documents/ 
cp -R Scripts/  Mod_Scripts  #復制整個目錄的內(nèi)容,在執(zhí)行cp –R命令之前借笙,目錄Mod_Scripts并不存在扒怖。它是隨著cp –R命令被創(chuàng)建的

軟硬連接

同一個文件可以有多個鏈接,不要建立鏈接的鏈接业稼。

ln -s data_file  sl_data_file  #建立軟連接時源文件使用絕對路徑
ln code_file  hl_code_file #硬鏈接本質(zhì)上是同一文件盗痒,享有同一個inode號

重命名文件

mv fall  fzll #重命名文件
mv fzll  Pictures/  #移動文件

刪除文件

rm -i fall 
rm -i f?ll #可使用通配符
rm -rf !(a|b)  #除a和b之外其它都刪除

目錄新建和刪除

mkdir New_Dir  #創(chuàng)建目錄
mkdir -p New_Dir/Sub_Dir/Under_Dir   #創(chuàng)建多個目錄和子目錄
rmdir New_Dir  #刪除目錄,rmdir只刪除空目錄
rm -i New_Dir/my_file 
tree 文件/目錄名  #了解文件或目錄結(jié)構(gòu)

文件查看

查看文件:head盼忌、tail积糯、 less、more谦纱、cat看成、

cat -n test1  #所有行都加行號
cat -b test1  #只有文本行加行號,空行不加跨嘉。
cat川慌、 less、 more是一回事兒
cat  #顯示全部祠乃,不易控制梦重。
more test1   #是分頁顯示
less test1   #less是more的升級版本
less -S #使文本整齊的顯示
less -N

head test1   #查看前十行
tail test1   #查看后十行
tail -n 2 test1  #查看后兩行
tail -2 test1  #查看后兩行

第 4 章 更多的 bash shell 命令

ps   #ps命令只會顯示運行在當前控制臺下的屬于當前用戶的進程
ps -f  #顯示完整格式的輸出
ps -ef  #查看系統(tǒng)上運行的所有進程
ps -ef|grep lixianlong  #只查看自己的進程記錄
ps -l  #S那一列,進程的狀態(tài)(O代表正在運行亮瓷; S代表在休眠琴拧; R代表可運行,正等待運行嘱支; Z代表僵化蚓胸,進程已結(jié)束但父進程已不存在; T代表停止)
top命令跟ps命令相似除师,能夠顯示進程信息沛膳,但top是實時顯示的
jobs -l  #可以查看當前終端生效的進程
kill -9 29485   #結(jié)束PID號為29485的進程,要檢查kill命令是否有效,可再運行ps或top命令汛聚,看看問題進程是否已停止
df -h   #查看所有已掛載磁盤的使用情況锹安。
du -sh  #查看當前位置每個文件大小
du -sh *   #查看當前位置所有文件大小總和

sort命令

一個例子掌握:將/etc/passwd文件按照用戶ID(以冒號分割第三列)進行降序的數(shù)值排序,并將排序結(jié)果輸出到/data1/lixianlong下面的test文件里面。

cat /etc/passwd |sort -t':' -k3 -nr -o /data1/lixianlong/test  
#即使test文件不存在叹哭,也會被創(chuàng)建出來忍宋;若test已存在,則原內(nèi)容會被覆蓋风罩。
-t 指定字段分隔符
-k 指定按分隔符分隔的第幾字段
-n 表示把數(shù)字識別成數(shù)字而不是字符讶踪;
-r 降序排列
-o 將結(jié)果輸出到指定文件

sort -M file  #將含有時間戳日期的文件按三字符的月份來排序
sort -u file   #u是unique的意思,就是每個只出現(xiàn)一次
cat file
111
222
222
333
333
333

cat a.txt|sort -u   #u是unique的意思泊交,就是每個只出現(xiàn)一次
111
222
333


grep命令

grep a test1  #在test1文件中搜索含有a的行
grep -n a test1   #在test1文件中搜索含有a的行,并顯示行號
grep -w a test1   #在test1文件中搜索含有嚴格匹配a的行
grep -v a test1  #在test1文件中搜索不含有a的行
grep [ab] test1  #搜索既含有a又含有b的行
grep -e a -e b test1  #同上柱查,搜索既含有a又含有b的行廓俭。

壓縮

gzip SRR*  #將SRR開頭的文件分別進行壓縮
tar -cvf test.tar SRR*  #將SRR開頭的文件全部壓縮進同一個文件,并命名為test.tar

解壓

gunzip SRR*  #將SRR開頭的壓縮文件分別解壓縮唉工,這個可以解壓縮.gz開頭的
tar -xvf test.tar  #將test.tar解壓到當前路徑

第 5 章 理解 shell

cat /etc/passwd |grep lixianlong  #在/etc/passwd文件中研乒,在用戶ID記錄的第7個字段中列出了默認的shell程序。只要用戶登錄到某個虛擬控制臺終端或是在GUI中啟動終端仿真器淋硝,默認的shell程序就會開始運行

ls -lF /bin/bash  #bash shell程序位于/bin目錄內(nèi)雹熬。從長列表中可以看出/bin/bash( bash shell)是一個可執(zhí)行程序:

shell的父子關(guān)系

生成子shell的三種方法:bash,進程列表谣膳,coproc

ps -f  #顯示進程
bash  #生成子shell
bash  #生成子shell的子shell
ps -f  #顯示進程竿报,發(fā)現(xiàn)多了兩個bash shell
echo $BASH_SUBSHELL  #該命令返回0,就表明沒有子shell继谚。如果返回1或者其他更大的數(shù)字烈菌,就表明存在子shell。
ps --forest  #展示這些子shell間的嵌套結(jié)構(gòu)
exit  #退出子shell的子shell
exit  #退出子shell

命令列表和命令分組

命令列表

pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls   #依次運行一系列命令使用分號(;)花履,這是命令列表

命令分組

進程列表

(pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls)  #括號括起來之后是進程列表芽世,會生成子shell來執(zhí)行該命令。
(pwd ; ls ; cd /etc ; pwd ; cd ; (pwd ; ls))  #會生成子shell的子shell诡壁。

放花括號里面的

{ command; }  #使用花括號進行命令分組不會創(chuàng)建子shell

置入后臺和顯示后臺作業(yè)

sleep 3000&  #sleep命令會在后臺( &)睡眠3000秒( 50分鐘)
ps -f  #顯示各種進程
jobs  #顯示出當前運行在后臺模式中的所有作業(yè)济瓢、作業(yè)狀態(tài)和對應(yīng)命令。
coproc sleep 10  #coproc命令是協(xié)程處理妹卿,自動置入后臺旺矾,不需要加&
ps -f  
coproc My_Job { sleep 10; }   # My_Job是給協(xié)程起的名字。

外部命令和內(nèi)建命令

內(nèi)建命令和外部命令的內(nèi)外是相對于shell而言的纽帖。
外部命令存在于bash shell之外宠漩,并不是shell程序的一部分,可用which和type命令找到它懊直,但which只顯示外部命令扒吁。

which ps
type -a ps

內(nèi)建命令和shell編譯成了一體,是shell的組成部分;可以用type命令來了解某個命令是否是內(nèi)建的雕崩。

type cd
type exit

內(nèi)建命令執(zhí)行速度更快魁索,因為內(nèi)建命不需要子進程,外部命令需要子進程盼铁;有些命令既有內(nèi)建命令也有外部命令粗蔚,比如echo和pwd;

命令別名

一個別名僅在它所被定義的shell進程中才有效饶火,想要在在子shell中也有效需要export該別名

alias -p  #查看當前可用的別名
alias li='ls -li'  #創(chuàng)建別名
li
bash
li
exit
li

第6章 使用Linux環(huán)境變量

全局環(huán)境變量對所有子shell都可見鹏控,局部變量只對創(chuàng)建它的shell可見。

printenv  #顯示全局變量肤寝,且不排序当辐。
env #顯示全局變量,且不排序鲤看。
set  #顯示全局變量缘揪、局部變量和用戶定義變量,并按字母順序排序义桂。
printenv HOME  #查看個別環(huán)境變量
echo $HOME  #查看個別環(huán)境變量
ls $HOME   #讓變量作為命令行參數(shù)

全局環(huán)境變量可用于進程的所有子shell

echo $my_variable
my_variable=Hello  #設(shè)置用戶定義變量找筝,變量名、等號和值之間沒有空格慷吊;
echo $my_variable

my_variable="Hello World"
echo $my_variable

系統(tǒng)環(huán)境變量都是大寫字母袖裕,所以自己創(chuàng)建的局部變量或是shell腳本,要使用小寫字母溉瓶,避免重新定義系統(tǒng)環(huán)境變量可能帶來的災(zāi)難陆赋。

創(chuàng)建全局環(huán)境變量

將局部環(huán)境變量導出到全局環(huán)境使用export,但是全局環(huán)境指的是該shell以及該shell的子孫shell嚷闭,無法使用export導出到該shell的父shell攒岛,想要在該shell的父shell中也能使用該變量需要寫入bashrc文件

bash
my_variable="I am Global now"
export my_variable  #將局部環(huán)境變量導出到全局環(huán)境
echo $my_variable
bash
echo $my_variable  #在子shelll中該變量依然可見
exit
exit
echo $my_variable  #在父shelll中該變量不可見
#總之一句話:老子可以改變兒子,兒子改變不了老子胞锰,除非寫入bashrc文件

刪除環(huán)境變量

unset my_variable  #用unset命令刪除變量灾锯,在子shell中刪除了一個全局環(huán)境變量,這只對子shell有效嗅榕。該全局環(huán)境變量在父shell中依然可用顺饮;但是在父shell中刪除一個全局變量,則子shell中該全局變量也消失凌那;

PATH 是一個默認的shell環(huán)境變量兼雄,是查找命令的目錄列表,由冒號分隔帽蝶;個人認為添加進PATH就是加進bashrc赦肋;因為是PATH是目錄列表,所以如果將軟件添加進bashrc,則只寫到該軟件的可執(zhí)行文件所在的文件夾即可佃乘,而不是將可執(zhí)行文件的名也寫上囱井!

PATH=$PATH:/home/christine/Scripts
export PATH="$PATH:/home/christine/Scripts"    #export一下之后子shell也能找到/home/christine/Scripts的程序的位置;如果是將下載的軟件寫入bashrc則此處只寫到文件夾位置趣避,不要將最后的可執(zhí)行文件名也寫上庞呕,因為寫入bashrc的是可執(zhí)行文件所在的文件夾;

$HOME表示的是某個用戶的主目錄程帕。它和波浪號( ~)的作用一樣住练。
.bashrc文件有兩個作用:一是查看/etc目錄下通用的bashrc文件,二是為用戶提供一個定制自己的命令別名和私有腳本函數(shù)的地方愁拭。

數(shù)組變量

mytest=(one two three four five)  #索引值分別是是0澎羞、1、2敛苇、3、4
echo ${mytest[2]} #環(huán)境變量數(shù)組的索引值都是從零開始顺呕,所以這表示顯示數(shù)組中的第3個數(shù)枫攀;
echo ${mytest[*]}  #顯示整個數(shù)組變量
mytest[2]=seven  #改變第三個數(shù)的值
unset mytest[2]   #unset命令刪除數(shù)組中的第3個值
echo {mytest[2] }  #該值雖然被刪,但是索引由空格占據(jù)
unset mytest  #刪除整個數(shù)組

第7章 理解Linux文件權(quán)限

顯示和設(shè)置默認八進制權(quán)限值

文件的全權(quán)限值是666(所有用戶都有r和w的權(quán)限)株茶,目錄的全權(quán)限值是777(所有用戶都有rwx權(quán)限)来涨。rwx對應(yīng)八進制值是4、2启盛、1分別表示可讀蹦掐、可寫、可執(zhí)行僵闯;
全權(quán)限值減去umask值就是新建文件(夾)的八進制權(quán)限值

-rw-r--r-- 1 lixianlong tanglab 0 Jun 25 13:11 tmp   #第一個字母表示文件夾后3個表示文件擁有者權(quán)限卧抗,再后3個是所屬群全權(quán)限,再后3個是其他人權(quán)限鳖粟;
umask  #顯示umask值
umask 026   # 設(shè)置默認八進制權(quán)限值社裆,0、2向图、6分別是擁有者泳秀、所屬群、其他人的八進制權(quán)限值
touch newfile2  # umask值設(shè)成026后榄攀,默認的文件權(quán)限值變成了640嗜傅,640就是該文件的八進制權(quán)限,即rw-r-----

更改權(quán)限

u代表擁有者檩赢; g代表所屬群吕嘀; o代表其他人; a代表上述所有;

touch newfile
chmod 760 newfile  # 賦予newfile權(quán)限為rwxrw----
chmod o+r newfile  # 其他人添加可讀權(quán)限
chmod u-x newfile  # 擁有者去除可執(zhí)行權(quán)限

第 9 章 安裝軟件程序

Centos是基于Red Hat企業(yè)版Linux源代碼構(gòu)建的免費發(fā)行版币他;

yum list installed  #找出系統(tǒng)上已安裝的包

從源碼安裝

直接到程序的官方站點下載
tar -zxvf sysstat-11.1.1.tar.gz  #解壓文件
cd sysstat-11.1.1
# README或AAAREADME文件坞靶。讀這個文件非常重要。該文件中包含了軟件安裝所需要的操作蝴悉。
./configure  #源代碼安裝的第一步彰阴,目的是對即將安裝的軟件進行配置,檢查當前環(huán)境是否滿足需要安裝的軟件的依賴關(guān)系拍冠,生成makefile文件
make  #一個軟件要想在linux上執(zhí)行必須是二進制文件尿这,make命令可以將軟件源碼編譯成二進制文件,make步驟結(jié)束時庆杜,可運行的sysstat軟件程序就會出現(xiàn)在目錄下射众!

第 10 章 使用編輯器

vim基礎(chǔ)

vim編輯器有兩種操作模式:普通模式(剛進入vim)和插入模式(按下i之后)
PageDown(或Ctrl+F):下翻一屏。
PageUp(或Ctrl+B):上翻一屏
q!:取消所有對緩沖區(qū)數(shù)據(jù)的修改并退出晃财。
w filename:將文件保存到另一個文件中叨橱。
wq:將緩沖區(qū)數(shù)據(jù)保存到文件中并退出
uu:普通模式下撤回上一步
gg:定位到第一行行首
shift+g:移動到最后一行

編輯數(shù)據(jù)

dd :普通模式下刪除當前光標所在行
dw :普通模式下刪除當前光標所在位置的單詞
d:刪除該行光標至行尾內(nèi)容 cat /dev/null > file.txt #刪除file.txt的所有內(nèi)容

查找替換(普通模式)

按下斜線( /)鍵,光標會跑到消息行断盛,然后vim會顯示出斜線罗洗,輸入你要查找的文本,按下回車鍵钢猛,點擊n表示下一個
s/old/new/g:一行命令替換所有old伙菜。
n,ms/old/new/g:替換行號n和m之間所有old。
%s/old/new/g:替換整個文件中的所有old命迈。
%s/old/new/gc:替換整個文件中的所有old贩绕,但在每次出現(xiàn)時提示。

一次性注釋多行與刪除多行注釋

第一步:打開vim
第二步:ctrl + v (此時左下角變?yōu)?VISUAL BLOCK)
第三步:上下移動光標壶愤,選上要注釋的行
第四步:點一下CAPS LOCK鍵進入大寫模式淑倾,再點一下i(此時左下角變?yōu)?INSERT)
第五步:shift + 3 ,然后再按ESC按鈕(等兩秒左右時間發(fā)現(xiàn)第三步選中的行都帶上了#)
第六步:wq保存即可

刪除多行注釋
同樣 Ctrl+v 進入列選擇模式,移到光標把注釋符選中征椒,直接按下d踊淳,注釋就被刪除了。

第 11 章 構(gòu)建基本腳本

date ; who  #兩個命令一起運行陕靠,date先運行迂尝,顯示當前日期和時間,who后運行剪芥,顯示當前是誰登錄到了系統(tǒng)上垄开;
date && who  #與上等價

創(chuàng)建 shell 腳本文件

#!/bin/bash    #這行必不可少,指定要使用的shell税肪,shell不會解釋以#開頭的行(除了以#!開頭的第一行)溉躲;

cat > test1
#!/bin/bash
date
who

chmod u+x test1  #擁有者有x權(quán)限才能執(zhí)行榜田,否則無法執(zhí)行;

使用變量

cat test1
#!/bin/bash
# This script displays the date and who's logged on
echo The time and date are:
date

echo -n "The time and date are: "  #echo后面加上-n參數(shù)則文本字符串和命令輸出顯示在同一行
date
echo "Let's see who's logged into the system:"
who
echo "User info for userid: $USER"  #引用變量要加$锻梳,會在腳本運行時替換成被引用內(nèi)容
echo "User info for userid: ${USER}"  #與上等價箭券,{}幫助識別美元符后的變量名,但是有時必須要用{}
echo  $11 #這表示輸出第一個位置參數(shù)后面加1
echo  ${11} # #這表示輸出第11個位置參數(shù)

echo "The cost of the item is \$15"  #$會被認為是在引用變量疑枯,加上轉(zhuǎn)移符(\)就會顯示符號本身辩块,通過${variable}形式引用的變量。變量名兩側(cè)額外的花括號通常用來荆永。

var1=1
var2=2
echo $var2 is larger than $var1

test1=`who`  #反引號實現(xiàn)命令替換废亭,test1獲得了who命令的輸出;反引號不是單引號具钥,反引號在Esc鍵下面豆村;
test2=$(date)  #$()也可以實現(xiàn)命令替換,test2獲得了date命令的輸出骂删;
echo $test1
echo $test2

today=$(date +%y%m%d)  #
ls /usr/bin -al > log.$today  #生成日志文件名常用的一種技術(shù)

輸入輸出重定向

> 實現(xiàn)輸出重定向掌动,若文件已存在則覆蓋
>> 實現(xiàn)追加數(shù)據(jù),原文件不會覆蓋宁玫,只會追加內(nèi)容

date > test6  #  >  實現(xiàn)輸出重定向
who >> test6  # >> 追加

wc < test6  #對test6文件進行wc操作

sort -n << end  # << 是內(nèi)聯(lián)輸入重定向粗恢,對以下輸入內(nèi)容進行<<左邊的處理,并且在輸入<< 右邊的內(nèi)容后結(jié)束
> 12
> 32
> 44
> 9
> end
9
12
32
44

 wc << ooo  #對以下輸入內(nèi)容進行<<左邊的處理撬统,并且在輸入<< 右邊的內(nèi)容后結(jié)束
> i am young
> i am strong
> i am hansom
> ooo
 3  9 35

管道

管道可以將一個命令的輸出作為另一個命令的輸入,但管道串起的兩個命令是同時運行

;和&&等價的敦迄,命令依次執(zhí)行恋追;|是前一個命令的輸出作為后一個命令的輸入,但實際上同時執(zhí)行

cat test1|wc  #將cat test1的結(jié)果作為wc命令的輸入罚屋,但是二者是同時運行的苦囱,第一個命令產(chǎn)生輸出的同時,輸出會立即送給第二個命令

#執(zhí)行以下三個知差別
cd .. | ls -F  #同時執(zhí)行cd .. 和ls -F
 cd .. ; ls -F  #先執(zhí)行cd .. 后執(zhí)行l(wèi)s -F
cd .. && ls -F  #先執(zhí)行cd .. 后執(zhí)行l(wèi)s -F

數(shù)學運算

expr

只支持整數(shù)運算

expr 10+2  # +的左右要有空格才可以成功運算
10+2

expr 1.5 \* 1.5  #expr只支持整數(shù)運算
expr: non-integer argument

expr 10 + 2
12

expr 10 - 2
8

expr 10 \* 2  #乘以號要使用轉(zhuǎn)義符進行轉(zhuǎn)義
20

expr 10 / 2
5
$ cat test6
#!/bin/bash
# An example of using the expr command
var1=10
var2=20
var3=$(expr $var2 / $var1)
echo The result is $var3

$ chmod u+x test6

$ ./test6

$[]

使用$[ ] 將數(shù)學表達式包起來脾猛,只支持整數(shù)運算

$ cat test1
#!/bin/bash
var1=$[1 + 5]
var2=$[$var1 * 2]
var3=2
var4=$[$var1 * ($var2 - $var3)]  # $[ ]里面的*不需要轉(zhuǎn)義撕彤,不會被看做通配符。
var5=$[1.5 * 1.5]  #這步代碼將失敗猛拴,因為$[]和expr一樣也只支持整數(shù)運算
echo $var1
echo $var2
echo The final result is $var4
echo $var5
$ chmod u+x test1
$ ./test1
The final result is 500

bc

bc基本用法

$ bc -q   # -q 選項可以不顯示冗長的歡迎信息羹铅。
scale=6   #在計算中保留的小數(shù)位數(shù)
var1=10
var1 * 4
40
var2 = var1 / 3
print var2
3.333333
quit   # 退出bc

在腳本中使用bc

例子1

$ cat test1
#!/bin/bash
var1=$(echo "scale=4; 3.44 / 5" | bc)
echo The answer is $var1

$ chmod u+x test1
$ ./test1
The answer is .6880

例子2

$ cat test1
#!/bin/bash
var1=20
var2=3.14159
var3=$(echo "scale=4; $var1 * $var1" | bc)
echo $var3
var4=$(echo "scale=4; $var3 * $var2" | bc)
echo $var4
var5=$(echo "scale=4; ($var1 + $var2)*$var3/$var4" | bc)
echo The final result is $var5

例子3
例子2可以改為如下

$ cat test2
#!/bin/bash
var1=20
var2=3.14159
var3=$(bc << eof
scale=4
$var1 * $var1
eof
)
echo $var3

var4=$(bc << ooo
scale=4
$var3 * $var2
ooo
)
echo $var4

var5=$(bc << tmp
scale=4
($var1 + $var2)*$var3/$var4
tmp
)

echo The final result is $var5

可以繼續(xù)改為如下

重點

表達式中用到的變量若是在表達式之外被賦值的則加上$,若是在表達式內(nèi)被賦值的則不加$

$ cat test3
#!/bin/bash
var1=20
var2=3.14159

var5=$(bc << eof
scale=4
var3=($var1 * $var1)
var4=(var3 * $var2)    # var3是在表達式內(nèi)被賦值的愉昆,不加$
($var1 + $var2)*var3/var4   # var3 和 var4都是表達式內(nèi)被賦值的职员,不加$
eof
)
echo The final result is $var5

$( )、$[ ]跛溉、${ }辨析

$( )焊切、$[ ]扮授、${ }作用分別是命令替換杭隙、數(shù)學運算檩禾、界定邊限

第 12 章 使用結(jié)構(gòu)化命令

if-then-fi

若if后面的命令可成功運行則執(zhí)行then后面的命令

#!/bin/bash
# testing the if statement
if pwd  # pwd可以換成date或who試下
then  #這一句和上一句可以合并為 if pwd  ; then
echo "It worked"
fi

if-then-else-fi

若if后面的命令可成功運行則執(zhí)行then后面的命令,否則執(zhí)行else后面的命令埃碱;

#!/bin/bash
if pwd
then echo pwd is available
else
echo pwd is not available
fi

if-then-elif-then-fi

if command1
then
command set 1
elif command2
then
command set 2
elif command3
then
command set 3
elif command4
then
command set 4
fi
若command1成功執(zhí)行則執(zhí)行command set 1嚎尤,否則執(zhí)行command2荔仁;
若command2成功執(zhí)行則執(zhí)行command set 2,否則執(zhí)行command3诺苹;
若command3成功執(zhí)行則執(zhí)行command set 3咕晋,否則執(zhí)行command4;
若command4成功執(zhí)行則執(zhí)行command set 4收奔;

#!/bin/bash
if PWD
then echo PWD is available
elif PWd
then echo PWD is not avaliable, but PWd is available
elif pwd
then echo PWD and PWd is not avaliable, but pwd is available
fi

test 命令

test命令可以在if-then語句中測試不同條件掌呜;test后的測試條件可以使用[ ]來替代,測試條件在[]中前后要空一格坪哄;test命令中不能使用帶小數(shù)點的值(因為bash shell只能識別整數(shù))质蕉。

test后沒有內(nèi)容和內(nèi)容為空都將執(zhí)行else

$ cat test1  
#!/bin/bash
if test  #可以改為if test [ ]   #test后沒有內(nèi)容將執(zhí)行else  
then
echo "True"
else
echo "False"
fi

$ ./test1
False
$ cat test1  
#!/bin/bash
my_variable=""
if test $my_variable  #可以改為if test [ $my_variable ]   # test后內(nèi)容為空將執(zhí)行else,不為空則執(zhí)行then  
then
echo "True"
else
echo "False"
fi

$ ./test1
False

test命令可以進行:數(shù)值比較翩肌、字符串比較模暗、文件比較

數(shù)值比較

e是equal; g是great念祭; l是less兑宇; n是not; t是than粱坤;

n1 -eq n2 檢查n1是否與n2相等
n1 -ge n2 檢查n1是否大于或等于n2
n1 -gt n2 檢查n1是否大于n2
n1 -le n2 檢查n1是否小于或等于n2
n1 -lt n2 檢查n1是否小于n2
n1 -ne n2 檢查n1是否不等于n2

$ cat test1
#!/bin/bash
value1=10  #如果是10.1就會無法判斷隶糕,bash shell只能處理整數(shù)
if [ $value1 -gt 5 ]  #條件與中括號前后要有一個空格
then
echo "$value1 is greater than 5"
fi

字符串比較

str1 = str2 檢查str1是否和str2相同
str1 != str2 檢查str1是否和str2不同
str1 < str2 檢查str1是否比str2小,
str1 > str2 檢查str1是否比str2大
-n str1 檢查str1的長度是否非0
-z str1 檢查str1的長度是否為0站玄,若該字符未被定義枚驻,會被認為是0

#!/bin/bash
# testing string equality
testuser=lixianlong
#
if [ $USER = $testuser ]
then
echo "Welcome $testuser"
fi

字符串比較時,26個英文字母從a到z是依次變大株旷,并且大寫小于小寫再登;而sort命令排序時,小寫字母大于大寫晾剖;注意:字符串比較不是比較字符串的長度锉矢!

$ cat test1
#!/bin/bash
val1=aa
val2=b
if [ $val1 \> $val2 ]  #大于號和小于號必須轉(zhuǎn)義,否則會認為是重定向
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi

$ ./test1
aa is less than b

文件比較

test命令的文件比較功能
比 較 描 述
-d file 檢查file是否存在并是一個目錄
-e file 檢查file是否存在
-f file 檢查file是否存在并是一個文件
-r file 檢查file是否存在并可讀
-s file 檢查file是否存在并非空
-w file 檢查file是否存在并可寫
-x file 檢查file是否存在并可執(zhí)行
-O file 檢查file是否存在并屬當前用戶所有
-G file 檢查file是否存在并且默認組與當前用戶相同
file1 -nt file2 檢查file1是否比file2新
file1 -ot file2 檢查file1是否比file2舊

$ cat test1
#!/bin/bash
if [ -d $HOME ] && [ -w $HOME/testing ]  # &&是邏輯和齿尽,兩個條件都滿足才能執(zhí)行then, ||是邏輯或沈撞,兩個條件有一個滿足就能執(zhí)行then
then
then
echo "The file exists and you can write to it"
else
echo "I cannot write to the file"
fi

(( ))和[[ ]]

(( ))里面可以使用高級數(shù)學表達式,并且>不需要轉(zhuǎn)義雕什,但是在[ ]中>進行判斷需要轉(zhuǎn)義

$ cat test1
#!/bin/bash
val1=10
if (( $val1 ** 2 > 90 ))  # **是雙括號命令符號的一種缠俺,表示冪運算
then
(( val2 = $val1 ** 2 ))
echo "The square of $val1 is $val2"
fi

$ ./test1
The square of 10 is 100

雙方括號可以通過正則表達式進行模式匹配显晶,不是所有的shell都支持雙方括號

$ cat test1
#!/bin/bash
if [[ $USER == l* ]]  #
then
echo "Hello $USER"
else
echo "Sorry, I do not know you"
fi

$ ./test1
Hello lixianlong

case命令

在一組可能的值中尋找特定值,需要很長的if-then-elif-then-else-fi語句壹士,使用case更方便磷雇;case命令提供了一個更清晰的方法來為變量每個可能的值指定不同的選項。

case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac

$ cat test1
#!/bin/bash
case $USER in
lixianlong | Jack | Summer) echo "Welcome, $USER"
echo "Shuntai Yu is the best!";;
Bitch)
echo "Fuck you ! son of bitch !";;
jessica)
echo "Do not forget to log off when you're done";;
*)
echo "Sorry, get out of here!";;
esac

輸入金陵十二釵人名可到對應(yīng)的判詞腳本

#!/bin/bash
case $1 in
daiyu | baochai|lindaiyu|xuebaochai)
echo "可嘆停機德躏救,堪憐詠絮才唯笙。"
echo "玉帶林中掛,金簪雪里埋盒使。";;

yuanchun|jiayuanchun)
echo "二十年來辨是非崩掘,榴花開處照宮闈。"
echo "三春爭及初春景少办,虎兔相逢大夢歸苞慢。";;

tanchun|jiatanchun)
echo 才自清明志自高,生于末世運偏消英妓。
echo "清明涕泣江邊望挽放,千里東風一夢遙。";;

xiangyun|shixiangyun)
echo 富貴又何為蔓纠?襁褓之間父母違辑畦。
echo "展眼吊斜輝,湘江水逝楚云飛腿倚。";;

miaoyu)
echo 欲潔何曾潔纯出,云空未必空。
echo "可憐金玉質(zhì)敷燎,終陷淖泥中暂筝。";;


yingchun|jiayingchun)
echo 子系中山狼,得志便猖狂懈叹。
echo "金閨花柳質(zhì)乖杠,一載夢黃梁分扎。";;

xichun|jiaxichun)
echo "堪破三春景不常澄成,緇衣頓改昔年妝。"
echo "可憐秀戶侯門女畏吓,獨臥青燈古佛旁墨状。";;

fengjie|wangxifeng)
echo "凡鳥偏從末世來,都知愛慕此生才菲饼。"
echo "一從二令三人木肾砂,哭向金陵事可哀。";;

liwan)
echo "桃李春風結(jié)子完宏悦,到頭誰似一盆蘭镐确?"
echo "如冰水好空相妒包吝,枉與他人作笑談。";;

qinkeqing)
echo "情天情涸春幻情身诗越,情既相逢必主淫。"
echo "慢言不肖皆榮出息堂,造釁開端實在寧嚷狞。";;

qinshishang|shishang|laoqin)
echo "FUCK YOU! 老秦";;
*)
echo "此人非金陵十二釵";;
esac

$ ./test1 xuebaochai
可嘆停機德,堪憐詠絮才荣堰。
玉帶林中掛床未,金簪雪里埋。

第 13 章 更多的結(jié)構(gòu)化命令

for-in-do-done

知識點1

復雜值用引號括住

$ cat test1
#!/bin/bash
for id in wuhan "New York"  don\'t "don't "  '“”' "$¥¥"   #復雜值可以用引號或者轉(zhuǎn)義符(\)
do
echo $id
done

$ ./test1
wuhan
New York
don't
don't
“”
$¥¥

知識點2

遍歷列表和給列表添加內(nèi)容

$ cat test1
#!/bin/bash
list="Guangzhou Shenzhen Shangqiu"  #給定一個列表
list=$list" Beijing"  #可以在列表后再加值振坚,注意:$list"后面有一個空格薇搁,不加空格會和最后一個詞融合成為一個。
for id in $list  #使用for去遍歷列表
do
echo "Have you ever visited $id?"
done

知識點3

遍歷外部文件列表

$ cat list
Guangzhou
Shenzhen
Shangqiu
Beijing

$ cat test1
#!/bin/bash
list="/home/lixianlong/list"  #給定一個列表屡拨,這里使用絕對路徑只酥,也可以使用相對于test1所在位置的相對路徑
for id in $(cat $list)  #使用for去遍歷列表
do
echo "Have you ever visited $id?"
done

知識點4

bash shell默認分隔符為空格、制表符呀狼、換行符裂允,若想更改分隔符需要指定IFS

$ cat name.txt
Jack,Bruce,Summer
Nick,Lily,Marry

$ cat test1
#!/bin/bash
IFS=$'\n',  #這里若寫成IFS=$'\n'則只識別換行符
name=name.txt
for id in $(cat $name)
do
echo My name is $id
done

知識點5

C語言的for

$ cat > test1
#!/bin/bash
for (( id=1; id <= 5; id++ ))
do
echo "The next number is $id"
done

$ ./test1
The next number is 1
The next number is 2
The next number is 3
The next number is 4
The next number is 5
$ cat > test1
#!/bin/bash
for (( id=1, foo=6; id <= 6, foo>=1; id++, foo-- ))
do
echo "$foo - $id"
done

$ ./test1
6 - 1
5 - 2
4 - 3
3 - 4
2 - 5
1 - 6

while-do-done

命令行形式

$ cat name.txt
Jack
Bruce
Summer

$ cat name.txt |while read id; do (echo my name is $id); done
my name is Jack
my name is Bruce
my name is Summer

腳本形式

$ cat test1
#!/bin/bash
var1=6
while [ $var1 -gt 0 ]
do
echo $var1
var1=$[ $var1 - 1 ]
done

$ ./test1
6
5
4
3
2
1

until-do-done

$ cat test1
#!/bin/bash
var1=100
until [ $var1 -eq 0 ]
do
echo $var1
var1=$[ $var1 - 25 ]
done

$ ./test1
100
75
50
25

通過嵌套循環(huán)實現(xiàn)

Q1
Outer loop: 5
Inner loop: 5 * 1 = 5
Inner loop: 5 * 2 = 10
Outer loop: 4
Inner loop: 4 * 1 = 4
Inner loop: 4 * 2 = 8
Outer loop: 3
Inner loop: 3 * 1 = 3
Inner loop: 3 * 2 = 6
Outer loop: 2
Inner loop: 2 * 1 = 2
Inner loop: 2 * 2 = 4
Outer loop: 1
Inner loop: 1 * 1 = 1
Inner loop: 1 * 2 = 2
Outer loop: 0
Inner loop: 0 * 1 = 0
Inner loop: 0 * 2 = 0

Q2
Outer loop: 3
Inner loop: 3 / 1 = 3.0000
Inner loop: 3 / 2 = 1.5000
Inner loop: 3 / 3 = 1.0000
Inner loop: 3 / 4 = .7500
Outer loop: 2
Inner loop: 2 / 1 = 2.0000
Inner loop: 2 / 2 = 1.0000
Inner loop: 2 / 3 = .6666
Inner loop: 2 / 4 = .5000
Outer loop: 1
Inner loop: 1 / 1 = 1.0000
Inner loop: 1 / 2 = .5000
Inner loop: 1 / 3 = .3333
Inner loop: 1 / 4 = .2500

控制循環(huán)

break和continue控制循環(huán)

break命令

break n n是從里層往外層數(shù)的,最里面的n為1哥艇。n若不寫則默認為1绝编,跳出當前循環(huán)。將n設(shè)為2貌踏,則跳出下一級外部循環(huán)十饥,以此類推。

continue命令

continue n n也是從里層往外層數(shù)的祖乳。

第 14 章 處理用戶輸入

位置參數(shù)

$ cat test1
#!/bin/bash
echo $1  #輸出第一個位置參數(shù)
echo $11  #輸出第一個位置參數(shù)逗堵,然后加1
echo ${11}  #輸出第11個位置參數(shù)

$ ./test1 a b c d e f g h i j k l 
a
a1
k

basename和dirname

$ cat test1
#!/bin/bash
echo $(basename $0)  #basename實現(xiàn)掐頭
echo $(dirname $0)  #dirname實現(xiàn)去尾
echo $0

$ bash /data1/lixianlong/wangxiao/2020-4-16/small/tmp/test1  #運行此腳本
test1  #掐頭后的結(jié)果
/data1/lixianlong/wangxiao/2020-4-16/small/tmp  #去尾后的結(jié)果
/data1/lixianlong/wangxiao/2020-4-16/small/tmp/test1

#也可以以下面的方式運行
$ chmod u+x test1  #賦予執(zhí)行權(quán)限
$ bash /data1/lixianlong/wangxiao/2020-4-16/small/tmp/test1  #直接運行腳本

$#、$*眷昆、$@

$#為位置參數(shù)的個數(shù)蜒秤; $*、$@為所有位置參數(shù)

$ cat  test1
echo $#
echo ${!#}   #輸出最后一個位置參數(shù)亚斋,不能使用${$#}作媚,因為花括號里面不能有$

$ ./test1 a b c
3  #位置參數(shù)的個數(shù)
c  #最后一個位置參數(shù)

$ ./test1 a b c d e f g
7
g
$ cat test1
echo $*
echo $@

$ ./test1 a b c d e f g
a b c d e f g
a b c d e f g

shift

shift n 將每個位置參數(shù)向左移動n個位置,這樣可以跳過不需要的位置參數(shù)帅刊。

$ cat test1
#!/bin/bash
echo "The original parameters: $*"
shift 2  #將每個位置參數(shù)向左移動n個位置
echo "Here's the new first parameter: $1"

$ ./test1 1 2 3 4 5
The original parameters: 1 2 3 4 5
Here's the new first parameter: 3

分離參數(shù)和選項

$ cat test1
#!/bin/bash
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the -a option" ;;
-b) echo "Found the -b option";;
-c) echo "Found the -c option" ;;
--) shift  #當出現(xiàn)--首先左移一位纸泡,然后跳出while循環(huán)
break ;;
*) echo "$1 is not an option";;
esac
shift  #這個shift與下面的$@呼應(yīng),每進來一個option赖瞒,這個shift都進行了移除女揭,不會再次出現(xiàn)
done
#
count=1
echo $@  #因為上面的shift將所有的option都移除了蚤假,所以這里只輸出--后的位置參數(shù)
for param in $@
do
echo "Parameter #$count: $param"
count=$[ $count + 1 ]
done


$ ./test1 -c -a -b test1 test2 test3
Found the -c option
Found the -a option
Found the -b option
test1 is not an option
test2 is not an option
test3 is not an option

$ ./test1 -c -a -b test1 -- test2 test3
Found the -c option
Found the -a option
Found the -b option
test1 is not an option
test2 test3
Parameter #1: test2
Parameter #2: test3

getopt :略

read

read的命令有一些選項
-p:直接在read命令行指定變量
-s:隱藏輸入的數(shù)據(jù)
-t:超時選項
-n:要求輸入特定數(shù)目字符

$ cat test1
#!/bin/bash
echo -n "Enter your name: "   # -n選項使用戶可以腳本輸入數(shù)據(jù)。
read id
echo "Hello $id, welcome to my program. "

$ ./test1
Enter your name: Summer
Hello Summer, welcome to my program.
$ cat test1
#!/bin/bash
read -p "Enter your name: " id foo   #-p直接在read命令行輸入變量吧兔,并且指定了兩個變量勤哗。
echo "Your first name is $id, your last name is $foo"

$ ./test1
Enter your name: Shuntai Yu
Your first name is Shuntai, your last name is Yu
$ cat test1
#!/bin/bash
if read -t5 -n9 -s -p "Enter your name: "
then
echo
echo "Your name is $REPLY"
else
echo
echo "Too late!"
fi

第 15 章 呈現(xiàn)數(shù)據(jù)

輸入重定向 <

cat可以顯示STDIN的輸入,而標準STDIN是指鍵盤輸入

$ cat
this is the first line  #這一行是鍵盤輸入的掩驱,即STDIN
this is the first line   #這一行是cat顯示的
this is the second line   #這一行是鍵盤輸入的芒划,即STDIN
this is the second line   #這一行是cat顯示的

<可以將STDIN強制變成文件

$ cat test1
this is the first line
this is the second line

$ cat < test1  # 將STDIN改成了test1文件,<稱為輸入重定向符號
this is the first line
this is the second line

輸出重定向 >

標準STDOUT是屏幕顯示欧穴,但是>可以將STDOUT導入文件

$ ls -l > test1  #本來要顯示在屏幕上的內(nèi)容被導進了文件民逼,這會覆蓋原內(nèi)容
$ ls -l >> test1   #這樣只追加,不覆蓋

$ cat test1
total 4
-rw-r--r-- 1 lixianlong tanglab 34 Jun 28 18:42 name.txt
-rwxr--r-- 1 lixianlong tanglab  0 Jun 30 12:02 test1

錯誤重定向2>

$ ./error.txt 2> test1  #將錯誤輸出導進文件

$ cat test1
-bash: ./error.txt: No such file or directory

1>和2> 正確和錯誤輸出分別導進不同文件

$ cat test
this is a test line

$ cat error.txt  #因為沒有 error.txt文件涮帘,所以會報錯
cat: error.txt: No such file or directory

$ cat test error.txt 1> T.txt 2> F.txt   # 1>將正確輸出導入T.txt拼苍,將錯誤輸出導入F.txt

$ cat T.txt
this is a test line

$ cat F.txt
cat: error.txt: No such file or directory

&>和1> S.txt 2>&1正確和錯誤輸出導進同一個文件

1> S.txt 2>&1 S.txt左邊表示正確的輸出導進S.txt文件,S.txt右邊錯誤的輸出當做正確的也導進該文件
2> S.txt 1>&2 S.txt左邊表示錯誤的輸出導進S.txt文件调缨,S.txt右邊正確的輸出當做錯誤的也導進該文件

巧記:>&前面的東西變成>&后面的東西疮鲫,比如1>&2是1變成2,1是正確的弦叶,2是錯誤俊犯,意思就是將本來正確的輸出變成錯誤的輸出。

$ cat test
this is a test line

$ cat test error.txt &> S.txt   # error.txt文件并不存在伤哺,所以cat它會報錯
$ cat test error.txt 1> S.txt 2>&1  #這句意思是將正確的輸出導進S.txt燕侠,2>&1表示將2變成1,也就是將本來錯誤的輸出變成正確的輸出立莉,也導進文件S.txt绢彤。

$ cat test error.txt > S.txt 2>&1    #1可以省略,這句與上兩句同
$ cat test error.txt 2> S.txt 1>&2    #這句意思是將錯誤的輸出導進S.txt蜓耻,1>&2表示將1變成2茫舶,也就是將本來正確的輸出變成錯誤的輸出,也導進文件S.txt刹淌。

$ cat S.txt
this is a test line
cat: error.txt: No such file or directory
$ cat test
echo "This is an error" >&2  # >&2等同于1>&2饶氏,表示將1變成2,本來該句是正確輸出芦鳍,現(xiàn)在被變成了錯誤輸出嚷往。
echo "This is normal output"

$ ./test  #標準STDOUT會將兩句都顯示
This is an error
This is normal output

$ ./test > T.txt   # > 只將正確輸出導入T.txt
This is an error  #這句被當成了錯誤輸出沒有導進去葛账,在屏幕上顯示了出來

$ cat T.txt  #T.txt里面只有正確輸出
This is normal output

$ ./test 2> F.txt  # 2> 只將錯誤輸出導入F.txt
This is normal output   #這句是正確輸出沒有導進去柠衅,在屏幕上顯示了出來

$ cat F.txt  #F.txt里面只有錯誤輸出
This is an error

阻止命令輸出

在Linux系統(tǒng)上null文件的標準位置是/dev/null。你重定向到該位置的任何數(shù)據(jù)都會被丟掉籍琳,不會顯示菲宴。將錯誤輸出導向它可避免出現(xiàn)錯誤消息贷祈,也不保存錯誤消息。

$ cat test
echo "this is a test"
echo "this is a test'  #這一句將會報錯

$ ./test 2> /dev/null #避免出現(xiàn)錯誤消息喝峦,也不保存錯誤消息势誊,只出現(xiàn)正確消息。
this is a test

$ ./test 1> /dev/null  #避免出現(xiàn)正確消息谣蠢,也不保存正確消息粟耻,只出現(xiàn)錯誤消息。
./test: line 2: unexpected EOF while looking for matching `"'
./test: line 3: syntax error: unexpected end of file

$ ./test 1> /dev/null 2>&1  #正確和錯誤的消息都不出現(xiàn)
$ ./test 2> /dev/null 1>&2  #正確和錯誤的消息都不出現(xiàn)

$ cat /dev/null

$ cat /dev/null > test  #將/dev/null內(nèi)容導入文件眉踱,會清除文件內(nèi)容
$ cat test

tee

tee命令可以分流挤忙,可將命令結(jié)果一部分顯示到屏幕上,另一部分導進文件谈喳,tee -a是追加到文件

$ cat test
111111

$ date |tee test  #tee命令分流册烈,并覆蓋test文件原內(nèi)容
Tue Jun 30 15:08:58 CST 2020

$ cat test
Tue Jun 30 15:08:58 CST 2020

$ date|tee -a test  #tee命令分流,并追加到test文件里
Tue Jun 30 15:08:58 CST 2020

$ cat test
111111
Tue Jun 30 15:14:32 CST 2020

第 16 章 控制腳本

后臺運行和nohup

命令后加&就是后臺運行婿禽,當后臺運行時赏僧,仍用終端顯示器來顯示STDOUT和STDERR消息。終端會話退出扭倾,后臺進程也會隨之退出淀零。加上nohup即使退出終端,命令也會一直運行到結(jié)束膛壹。

$ cat test
#!/bin/bash
count=1
while [ $count -le 10 ]
do
sleep 1
echo $count
count=$[ $count + 1 ]
done

$ ./test &  #命令后加&就是后臺運行
$ nohup ./test &  #退出putty也沒關(guān)系窑滞。但對相同目錄中的多個文件nohup時要小心,因為所有的輸出都會被發(fā)送到同一個nohup.out文件中恢筝,這會造成混亂哀卫。

Ctrl+C 和 Ctrl+Z 和jobs -l

Ctrl+C  #中斷進程
Ctrl+Z   #暫停進程,
ps -l   #顯示進程
kill -9 PID號   #殺掉該PID號的進程

jobs   #查看shell正在處理的作業(yè)
jobs -l    #還可看到作業(yè)的PID

$ cat test-1
#!/bin/bash
count=1
while [ $count -le 10 ]
do
sleep 1
echo $count甲
count=$[ $count + 1 ]
done

重啟停止的作業(yè)

$ jobs -l
[1]- 32358 Stopped                 ./test  #[ ]里面的1才是作業(yè)號,莫搞錯
[2]+ 32428 Stopped                 ./test-2

$ bg    #若只有一個被暫停的作業(yè)撬槽,可以直接bg或者fg
$ bg 1  #多個作業(yè)bg加作業(yè)號可以放到后臺重啟該作業(yè)號對應(yīng)的作業(yè)
$ bg 2
$ fg 1   #fg加作業(yè)號可以放到前臺重啟該作業(yè)
$ fg 2

定時運行作業(yè)

使用at命令此改。設(shè)置開始運行的時間有很多種格式,具體參考書本

$ at -f test-2 now  #-f指定要運行的文件侄柔,文件后為開始運行的時間
job 27 at Tue Jun 30 20:42:00 2020
You have mail in /var/spool/mail/lixianlong  #去 /var/spool/mail/lixianlong就可以找到上面命令的輸出結(jié)果共啃,有時候這句可能沒有,可以使用jobs命令試一下暂题。知道地方在哪里就可以了移剪。

$ at -f test-2 now+1min  #從現(xiàn)在起1min之后運行test-2腳本

$ atq   #atq命令可以查看系統(tǒng)中有哪些作業(yè)在等待
$ atrm 18  #atrm加作業(yè)號就可刪除,作業(yè)號是第一列

第 17 章 創(chuàng)建函數(shù)

定義函數(shù)的兩種方法

方法1
function 函數(shù)名 {
命令行
}

方法2
函數(shù)名() {
命令行
}

$ cat test
#!/bin/bash
function funct {          #這一行可改為funct () { 
echo "This is an example of a function"
}
sleep 5
funct  #這里直接使用上面定義好的函數(shù)名薪者,注意纵苛,不要加$

$ ./test-2   #睡眠5秒之后執(zhí)行funct
This is an example of a function

向函數(shù)傳遞參數(shù)

bash shell會將函數(shù)當作小型腳本來對待。這意味著你可以像普通腳本那樣向函數(shù)傳遞參數(shù);

$ bar=666  #在命令行賦值一個變量

$ cat test
#!/bin/bash
tmp=888   #在腳本中賦值一個變量
#
function funct {
echo $1  #這個$1是函數(shù)的第一個位置參數(shù)
echo $2
echo $tmp  #函數(shù)可以使用腳本中賦值的變量攻人,這句可以執(zhí)行
echo $bar  #函數(shù)不可以使用命令行賦值的變量取试,這句將無法執(zhí)行
}
#
echo $bar  #腳本無法輸出$bar,因為腳本運行新開了一個shell怀吻,無法使用命令行賦值的變量瞬浓,想運行該句,需要提前執(zhí)行export bar
echo $tmp  #腳本可以使用腳本中賦值的變量
arg=6
foo=$(funct 10 20 $3)  #向函數(shù)funct傳遞三個位置參數(shù)蓬坡,$3意思是將腳本的第四個位置參數(shù)傳遞了進來猿棉,這樣就將腳本的位置參數(shù)傳給了函數(shù)。
echo $foo  #函數(shù)中的echo $bar將無法執(zhí)行屑咳,因為bar是命令行賦值的變量铺根,但是提前執(zhí)行export bar,函數(shù)中的echo $bar也可以執(zhí)行乔宿。

$ ./test 111 222 333
                  #$bar 無法輸出位迂,所以這行空白
888
10 20 888

$ export bar  #命令行中通過export將bar變成全局變量

$ ./test 111 222 333
666
888
10 20 888 666

local

local可以將變量局限于函數(shù)內(nèi)部。
下面的例子函數(shù)變量和腳本變量重名详瑞,加上local之后可以分開

$ cat test
#!/bin/bash
#
function funct {
tmp=$[ $value + 5 ]  #這一句改成local tmp=$[ $value + 5 ] 則這個tmp變量只局限于函數(shù)內(nèi)
result=$[ $tmp * 2 ]
}
#
tmp=4
value=6
funct
echo "The result is $result"
if [ $tmp -gt $value ]
then
echo "tmp is larger"
else
echo "tmp is smaller"
fi

$ ./test
The result is 22
tmp is larger

#若在函數(shù)中的tmp前加上local則結(jié)果與上相反
$ ./test
The result is 22
tmp is smaller

數(shù)組變量和函數(shù)

將該數(shù)組變量作為函數(shù)參數(shù)掂林,函數(shù)只會取數(shù)組變量的第一個值。

$ cat test
#!/bin/bash
function foo {
echo "The parameters are: $@"
thisarray=$1
echo "The received array is ${thisarray[*]}"
}
myarray=(1 2 3 4 5)
echo "The original array is: ${myarray[*]}"
foo $myarray  #將$myarray作為函數(shù)的位置參數(shù)坝橡,但是函數(shù)只取了數(shù)組變量的第一個值泻帮。
foo ${myarray[*]}

$ ./test
The original array is: 1 2 3 4 5
The parameters are: 1
The received array is 1
The parameters are: 1 2 3 4 5
The received array is 1

函數(shù)遞歸

局部函數(shù)變量的一個特性是自成體系。除了從腳本命令行處獲得的變量计寇,自成體系的函數(shù)不
需要使用任何外部資源锣杂。這個特性使得函數(shù)可以遞歸地調(diào)用,也就是說番宁,函數(shù)可以調(diào)用自己來得到結(jié)果元莫。

算法實現(xiàn):5! = 1 * 2 * 3 * 4 * 5 = 120

$ cat > test
#!/bin/bash
function factorial {
if [ $1 -eq 1 ]
then
echo 1
else
local temp=$[ $1 - 1 ]
local result=$(factorial $temp)
echo $[ $result * $1 ]
fi
}
read -p "Enter value: " value
result=$(factorial $value)
echo "The factorial of $value is: $result"

函數(shù)調(diào)用

函數(shù)可以放在腳本中隨時調(diào)用(創(chuàng)建函數(shù)庫);也可以使用一次性的函數(shù)(命令行創(chuàng)建函數(shù))蝶押;也可以放在bashrc中永久化踱蠢;

創(chuàng)建函數(shù)庫

函數(shù)庫可以在多個腳本中使用同一段代碼,不需要在每個腳本中都定義一次函數(shù)棋电。

$ cat myfuncts
function addem {
echo $[ $1 + $2 ]
}
function multem {
echo $[ $1 * $2 ]
}
function divem {
if [ $2 -ne 0 ]
then
echo $[ $1 / $2 ]
else
echo -1
fi
}

$ cat test
#!/bin/bash
. ./myfuncts   #這句可以改寫成source ./myfuncts茎截,這句執(zhí)行之后才可以調(diào)用庫中的函數(shù),這里的./使用的相對路徑赶盔,也可以使用具對路徑企锌,這句改寫成 . /data1/lixianlong/wangxiao/2020-4-16/small/tmp/myfuncts  
tmp=$(addem 10 15)
foo=$(multem 10 15)
arg=$(divem 10 15)
echo $tmp
echo $foo
echo $arg

$ ./test
25
150
0

命令行上創(chuàng)建函數(shù)

命令行上定義函數(shù)可以單行定義,也可以多行定義

#單行定義
$ function divem { echo $[ $1 / $2 ]; }   #注意加分號和空格

$ divem 100 5
20

#多行定義
$ function tmp {
> echo $[ $1/$2 ]
> }

$ tmp 100 5
20

函數(shù)放在.bashrc中

把函數(shù)放在.bashrc中有兩種方法于未,一種是直接在.bashrc文件中定義函數(shù)撕攒,還有一種是將寫有很多函數(shù)的函數(shù)庫腳本寫進.bashrc

$  cat >> ~/.bashrc
foo() { echo $[ $1+$2 ]; }

$ source ~/.bashrc
$ foo 1 1
2

將myfuncts文件寫進.bashrc使其永久化陡鹃。

cat >> ~/.bashrc
source /data1/lixianlong/wangxiao/2020-4-16/small/tmp/myfuncts

$ source ~/.bashrc

$ addem 10 2
12

$ multem 10 2
20

$ divem 10 2
5

第 19 章 初識sed和gawk

sed 的三個選項
-e 多個命令; -f 命令放在文件中打却; -n 不產(chǎn)生命令輸出。

$ cat test
The: quick brown fox jumps over the lazy: dog.
The: quick brown fox jumps over the lazy: dog.
The: quick brown fox jumps over the lazy: dog.
The: quick brown fox jumps over the lazy: dog.

$ cat script.sed
s/brown/green/
s/dog/cat/' 

sed執(zhí)行多個命令要用-e谎倔,命令之間用分號柳击,命令末尾和分號緊挨著。
如果不想用分號片习,也可以用bash shell中的次提示符來分隔命令捌肴。只要輸入第一個單引號標示
出sed程序腳本的起始( sed編輯器命令列表), bash會繼續(xù)提示你輸入更多命令藕咏,直到輸入了標示
結(jié)束的單引號状知。

將test內(nèi)容變成下面的

The: quick green fox jumps over the lazy: cat.
The: quick green fox jumps over the lazy: cat.
The: quick green fox jumps over the lazy: cat.
The: quick green fox jumps over the lazy: cat.

**方法1:**單行寫命令加命令之間加分號
$ sed -e 's/brown/green/; s/dog/cat/' test

**方法2:**多行寫命令不加分號,直接換行
$ sed -e '
> s/brown/green/
> s/dog/cat/' test

**方法3:**將命令放入腳本
sed -f script.sed test

gawk

-F指定分隔符孽查; -f指定文件
讓test文件中:分隔的第一部分變成aaa饥悴,然后再讓改換之后的第一步分is very love最后一部分,然后在處理數(shù)據(jù)前運行一句話This is begin:盲再,在處理數(shù)據(jù)后運行一句話This is end西设。

gawk的模式

極簡模式:gawk '{}' 文件

簡單模式:gawk 選項 尋址 '{print }' 文件

選項 -F指定分隔符 --re-interval識別正則表達式間隔

**方法1:**單行寫命令加命令之間加分號
$ gawk -F: 'BEGIN {print "This is begin:"}
{$1="aaa"; print $1 " is very love " $3}
END {print "This is end"}' test

**方法2:**多行寫命令不加分號,直接換行
$ gawk -F: 'BEGIN {print "This is begin:"}
{$1="aaa"
print $1 " is very love " $3}
END {print "This is end"}' test

**方法3:**將命令放入腳本
$ cat script   
BEGIN {print "This is begin:"}
{$1="aaa"; print $1 " is very love " $3}
END {print "This is end"}

$ gawk -F: -f script test

**方法3`-1:**將命令放入腳本
$ cat script
BEGIN {print "This is begin:"}
{$1="aaa"
foo=" is very love "
print $1 foo $3}   #gawk引用變量時不加$答朋,并且注意該變量要定義到該{ }里面贷揽,不要定義錯位置。
END {print "This is end"}

$ gawk -F: -f script test

sed基礎(chǔ)

sed的模式

極簡模式:sed '{}' 文件

簡單模式:sed 選項 '{[地址][命令] 新內(nèi)容}' 文件

當命令只有一條的時候可去掉花括號梦碗,有多條命令則命令之間用分號禽绪,或者每條命令另起一行。
選項 -n禁止輸出
地址和命令緊挨著
地址:可以數(shù)字行尋址洪规,也可以字符匹配行尋址
命令:s替換印屁,d刪除,a后追加斩例,ir插入库车,c修改,y轉(zhuǎn)換字符

w只保存匹配模式的行

$ cat test
This test is the first test  #/bin/bash
This test is the second test  #/bin/bash
This test is the third test
this line is so stupid
This test is the fourth test
this line is another stupid line


$ sed 's/test/trial/2' test   #對每一行的第2處匹配進行替換
$ sed 's/test/trial/g' test   #對文本所有匹配處進行替換
$ sed 's/test/trial/gw tmp.txt' test   #對文本所有匹配處進行替換樱拴,然后結(jié)果保存進tmp.txt文件
$ sed -n 's/test/trial/gpw tmp.tx' test   #對文本所有匹配處進行替換柠衍,然后結(jié)果保存進tmp.txt文件,并將被替換命令修改過的行輸出到顯示屏(-n和p結(jié)合即是此意晶乔。)

#將/bin/bash換成/bin/csh有以下兩種方法:
$ sed -n 's/\/bin\/bash/\/bin\/csh/gpw tmp.tx' test    #方法1:對 / 進行轉(zhuǎn)義
$ sed -n 's!/bin/bash!/bin/csh!gpw tmp.tx' test    #方法1:使用 ! 來替代 / 作為字符串的分隔符號

$ sed -n '2,3s/test/trial/2pw tmp.txt' test   #對文本的第2,3兩行進行替換珍坊,并將替換結(jié)果保存進tmp.txt文件
$ sed -n '2,$s/test/trial/2pw tmp.txt' test   #對文本的第2到最后一行進行替換,并將替換結(jié)果保存進tmp.txt文件

$ sed -n '{
2,3s/test/trial/2pw tmp.txt
3,$s/test/trial/1w foo.txt
}' test    #對文件2,3兩行第二處匹配的test替換為trial正罢,并將替換好的結(jié)果存進tmp.txt(注意只存匹配的行)阵漏;同時將文件3到尾行第一處匹配的test替換為trial,并將替換好的結(jié)果存進foo.txt(注意只存匹配的行)


#d是刪除;i是前面插入履怯;a是后面追加回还;c是替換;
$ sed '3,$d' test   #將第3行至最后一行刪除
$ sed '/stupid/d' test   #將含有stupid的行刪除
$ sed '/second/,/stupid/d' test   #second觸發(fā)刪除叹洲,stupid終止刪除柠硕。將匹配second的行(注意second第一次出現(xiàn))至匹配stupid 的行(注意stupid第一次出現(xiàn))都刪除。


$ sed '3,5i oooooo' test   #在test文本第3到第5行每行前面插入一行oooooo运提;將i換成a就是行后面追加蝗柔;將i換成c就是改變內(nèi)容
$ sed '3,5i\
oooooo' test   #與上同只不過改成了兩行

$ sed '/stupid/i oooooo' test    #與上同,只不過改變了尋址方式



$ cat foo.txt
ooooooooo
ooooooooo

$ sed '3r foo.txt' test   #將foo.txt的文本內(nèi)容完整的插入test文件的第3行
This test is the first test  #/bin/bash
This test is the second test  #/bin/bash
This test is the third test
ooooooooo
ooooooooo
this line is so stupid
This test is the fourth test

sed的單字符轉(zhuǎn)換

使用y

$ sed '1y/bin/-!&/' test   #將第一行的字符b變成-民泵,所有的i變成!癣丧,所有的n變成&。注意并不是將bin變成-!&栈妆,將bin變成-!&應(yīng)該使用sed的s命令而不是y命令
Th!s test !s the f!rst test  #/-!&/-ash
This test is the second test  #/bin/bash
This test is the third test
this line is so stupid
This test is the fourth test

第 20 章 正則表達式

從大量數(shù)據(jù)中過濾出特定數(shù)據(jù)需要正則表達式胁编,通過正則表達式來定義模式模板。
sed和gawk使用的正則表達式不同
sed只可使用基礎(chǔ)正則表達式( basic regular expression鳞尔, BRE)掏呼;
gawk使用擴展正則表達式( extended regular expression, ERE)铅檩。

特殊字符

有些字符在正則表達式模式中有特殊意義憎夷,想將這些特殊字符當做文本字符來看就必須使用反斜線( \)轉(zhuǎn)義。正則表達式識別的特殊字符包括:
{} [] () \ ^ + | * . $

轉(zhuǎn)義之后就被當做文本字符
巧記
大中小括號 {} [] ()
拄棍戴著帽 \ ^
加一星點錢? + | * . $ ?

sed的特殊字符

^ 鎖定在行首或者排除
$ 鎖定行尾
. 必須有一個字符昧旨,且不能是換行符

  • 字符后面放置星號表明該字符必須在匹配模式的文本中出現(xiàn)0次或多次拾给。

gawk的特殊字符

下面是gawk可識別而sed不可識別的
? 置于字符后,表示出現(xiàn)0次或1次

  • 至少出現(xiàn)1次
    { }
    | 是邏輯OR兔沃,定義多個匹配模式
    ( ) 表達式使用()進行分組

sed使用特殊字符例子

$ cat > test
^aaa$ooo^aaa$the cost is $4
\ is a special character
the book store
aaa
aaaa

^aaa$
^aaa$ooo^aaa$
cat
ccat
 at
hat
eat
fat
jat
*at
no
NO
No
188

$ sed -n '{/\$/p
> /\\/p        #將含有$的打印
> /^the/p        #將行首為the的打印
> /store$/wfoo.txt        #將行尾為store的存進文件foo.txt
>/^aaa$/p        #將只含有aaa的行打印
>/\^aaa\$/p        #將含有^aaa$的行打印
>/[^ch]at/p       #將不含cat和hat的行打印
>/^\^aaa\$$/p        #將只含有^aaa$的行打印
>/.at/p        #將at前至少有一個字符的行打印
>/[ch]at/p        #將含有cat或者hat的行打印
>/[Nn][Oo]/p        #將含有NO或者no或者No或者nO的行打印
>/^[0-9][0-9][0-9]$/p    #將只含有三位數(shù)的行打印
>/[c-eh-j]at/p    #將含cat或者dat或者eat或者hat或者iat或者jat的行打印
>/c*at/p       #表示字符c出現(xiàn)0次或多次
>/c.*at/p       # .表示此處必須有一個字符蒋得,*表示字符出現(xiàn)0次或多次,c at屬于空格也算乒疏。
}' test

$ sed '{/^$/d}' test        #將空白行去掉 

BRE還包含了一些特殊的字符組额衙,很好記,模式就是 [[:單詞:]]怕吴,所以只需要記幾個單詞就可以

[[:alpha:]] 匹配任意字母字符窍侧,不管是大寫還是小寫
[[:alnum:]] 匹配任意字母數(shù)字字符0~9、 AZ或az
[[:blank:]] 匹配空格或制表符
[[:digit:]] 匹配0~9之間的數(shù)字
[[:lower:]] 匹配小寫字母字符a~z
[[:print:]] 匹配任意可打印字符
[[:punct:]] 匹配標點符號
[[:space:]] 匹配任意空白字符:空格转绷、制表符伟件、 NL、 FF议经、 VT和CR
[[:upper:]] 匹配任意大寫字母字符A~Z
可以在正則表達式模式中將特殊字符組像普通字符組一樣使用

$ cat test
adfdhgfdghf
SFGDFGDFG

1234
12SD
,,..:

$ sed -n '/[[:lower:]]/p' test   #輸出小寫字母斧账,將lower換成其他單詞就可換成其他的

gawk使用特殊字符例子

gawk可以識別而sed不能識別的ERE(擴展正則表達式)
? {} | ()

$ echo "bt"|sed -n '/be?t/p'    #沒有結(jié)果谴返,因為sed不能識別?
$ echo "bt"|gawk '/be?t/{print $0}'    #gawk可以識別?
$ echo "bet" | gawk --re-interval '/be{1,2}t/{print $0}'    #be{1,2}t表示e至少出現(xiàn)1次,最多出現(xiàn)2次
$ echo "He has a hat." | gawk '/[ch]at|dog/{print $0}'    #  | 是邏輯OR咧织,定義多個匹配模式嗓袱。意思就是有cat,hat或者dog的都算匹配上
$ echo "Sat" | gawk '/Sat(urday)?/{print $0}'    #urday這個字符串出現(xiàn)0次或者1次习绢。使用()進行分組
$ echo "cat" | gawk '/(c|b)a(b|t)/{print $0}'   #cab渠抹,cat,bab毯炮,bat都算匹配上
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逼肯,一起剝皮案震驚了整個濱河市耸黑,隨后出現(xiàn)的幾起案子桃煎,更是在濱河造成了極大的恐慌,老刑警劉巖大刊,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件为迈,死亡現(xiàn)場離奇詭異,居然都是意外死亡缺菌,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剂陡,“玉大人,你說我怎么就攤上這事〗埃” “怎么了?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵窟社,是天一觀的道長灿里。 經(jīng)常有香客問我匣吊,道長色鸳,這世上最難降的妖魔是什么命雀? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上匈织,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好劲件,可當我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著厌蔽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奴饮。 梳的紋絲不亂的頭發(fā)上择浊,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天逾条,我揣著相機與錄音琢岩,去河邊找鬼师脂。 笑死吃警,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的谒府。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼债蓝,長吁一口氣:“原來是場噩夢啊……” “哼壳鹤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起饰迹,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤芳誓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后啊鸭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锹淌,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年赠制,在試婚紗的時候發(fā)現(xiàn)自己被綠了赂摆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡钟些,死狀恐怖烟号,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情政恍,我是刑警寧澤汪拥,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站篙耗,受9級特大地震影響迫筑,放射性物質(zhì)發(fā)生泄漏尤泽。R本人自食惡果不足惜明棍,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧揩晴,春花似錦、人聲如沸髓梅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坟募。三九已至岛蚤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間懈糯,已是汗流浹背涤妒。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赚哗,地道東北人她紫。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像屿储,于是被迫代替她去往敵國和親贿讹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,066評論 2 355