Linux-bash笔记
一、bash 基礎
1.變量累加
name=${name}yes <#以此例較佳! echo $a$b2.上個執行指令的回傳值 echo $?
[dmtsai@study ~]# echo $SHELL /bin/bash #可順利顯示!沒有錯誤! [dmtsai@study ~]# echo $? 0 <#因為沒問題,所以回傳值為 0 [dmtsai@study ~]# 12name=VBird bash: 12name=VBird: command not found... #發生錯誤了!bash回報有問題 [dmtsai@study ~]# echo $? 127 #因為有問題,回傳錯誤代碼(非為0)*使用?判斷變量值 [root@localhost ddd]# unset str [root@localhost ddd]# str=string1 [root@localhost ddd]# echo ${str} string1 #此時能讀到 [root@localhost ddd]# unset str [root@localhost ddd]# echo ${str?無此變量} #判斷是否有str,有則打印沒有則輸出;;使用echo ${str:-"不存在"} -bash: str: 無此變量#echo;在 Linux 下用 > 和 >> 表示,> 表示輸出到一個新文件中,而 >> 則表示輸出到 現有文件的末尾。3.鍵盤讀取read
[dmtsai@study ~]# read [-pt] variable 選項與參數: -p :后面可以接提示字符! -t :后面可以接等待的“秒數!”這個比較有趣~不會一直等待使用者啦! #eg: [root@localhost ~]# read -p"input contents" -t10 input contents #-t默認30秒4.declare / typeset
* declare/typeset [dmtsai@study ~]# declare [-aixr] variable 選項與參數: -a :將后面名為 variable 的變量定義成為陣列 (array) 類型 -i :將后面名為 variable 的變量定義成為整數數字 (integer) 類型 -x :用法與 export 一樣,就是將后面的 variable 變成環境變量; -r :將變量設置成為 readonly 類型,該變量不可被更改內容,也不能 unset 范例一:讓變量 sum 進行 100+300+50 的加總結果 [dmtsai@study ~]# sum=100+300+50 [dmtsai@study ~]# echo ${sum} 100+300+50 以文本打印 [dmtsai@study ~]# declare -i sum=100+300+50 [dmtsai@study ~]# echo ${sum} 450 #-i以數字計算5.與文件系統及程序的限制關系: ulimit
#文件太大無法在系統生成的問題:1.檢查ulimit 2.使用split進行文件分區 大文件分成小文件 [dmtsai@study ~]# ulimit [-SHacdfltu] [配額] 選項與參數: -H :hard limit ,嚴格的設置,必定不能超過這個設置的數值; -S :soft limit ,警告的設置,可以超過這個設置值,但是若超過則有警告訊息。在設置上,通常 soft 會比 hard 小,舉例來說,soft 可設置為 80 而 hard設置為 100,那么你可以使用到 90 (因為沒有超過 100),但介于 80~100 之間時,系統會有警告訊息通知你! -a :后面不接任何選項與參數,可列出所有的限制額度; -c :當某些程序發生錯誤時,系統可能會將該程序在內存中的信息寫成文件(除錯用), 這種文件就被稱為核心文件(core file)。此為限制每個核心文件的最大容量。 -f :此 shell 可以創建的最大文件大小(一般可能設置為 2GB)單位為 KBytes -d :程序可使用的最大斷裂內存(segment)容量; -l :可用于鎖定 (lock) 的內存量 -t :可使用的最大 CPU 時間 (單位為秒) -u :單一使用者可以使用的最大程序(process)數量。6.自定義命名 alias/unalias
alias lm='ls -al | less' #文件多的情況下,可以分頁顯示*,也可以使用關鍵字搜索;但是*匹配也可以7.history/HISTSIZE
history如何顯示時間、IP等信息
[root@localhost a5_dtx]# HISTSIZE=5 #可以登出重新寫入.bash_profile 或者用history -w強制寫入 [root@localhost a5_dtx]# echo ${HISTSIZE} 5 [root@localhost a5_dtx]# history 700 echo ${HISTSIZE}701 history 702 HISTSIZE=5703 echo ${HISTSIZE}704 history8.關于進程被掛起
jobs -l #查看掛起進程 fg 關鍵字 #喚起進程,或者fg [NUM]9.萬用字符(wildcard)與特殊符號
10.命令執行的判斷依據: ; , &&, ||
* cmd1;cmd2 不判斷直接執行 * cmd1&&cmd2 指令1正確($?=0)的情況下執行指令2;批量執行腳本神器 超級方便 * cmd1||cmd2 指令1正確則不執行指令2,指令1不正確則執行指令2 ls /etc/profile111 && echo "exist" || echo "not exist" && touch /etc/profile11111.統計行數、字符等:wc
[dmtsai@study ~]# wc [-lwm] 選項與參數: -l :僅列出行; -w :僅列出多少字(英文單字); -m :多少字符; #eg1: 檢測是否存在mysql進程,存在返回0,不存在返回1 [root@localhost ddd]# ps aux|grep mysql|grep -v 'color' && echo "process mysql exist" || echo "process mysql not exist" process mysql not exist #eg2:檢測是否存在mysql進程,存在返回1,不存在返回0 [root@localhost ddd]# ps aux|grep mysql|grep -v 'color'|wc -l && echo "process mysql not exist" || echo "process mysql exist" 0 process mysql exist12.快捷鍵補充
* ctrl+r:搜索歷史輸入命令 避免history的低效率 * ctrl+u/k:向前/后 刪除指令串 * ctrl+a/e:代替home/end鍵,到指令串的最前或者最后 * ctrl+s/q:凍結/解凍前端13.cut指令
[dmtsai@study ~]# cut -d'分隔字符' -f fields filename#用于有特定分隔字符 [dmtsai@study ~]# cut -c 字符區間 filename #用于排列整齊的訊息 對列處理 選項與參數: -d :后面接分隔字符。與 -f 一起使用; -f :依據 -d 的分隔字符將一段訊息分區成為數段,用 -f 取出第幾段的意思; -c :以字符 (characters) 的單位取出固定字符區間; #eg: [root@localhost ddd]# cat test.txt 1:2:3:4:5:6:a:b:c:d:e:f [root@localhost ddd]# cat test.txt | cut -d ':' -f 2,3 2:3 #以:為分隔符,取出第2至3段;;;或者cut filename [root@localhost ddd]# cat test.txt | cut -c 2-5 :2:3 #取出第2到5個的字符;2-表示取出第二個以及之后的字符14.字符轉換命令: tr, col, join, paste, expand
# 目前使用頻率低 僅做記錄 [dmtsai@study ~]# tr [-ds] SET1 ... 選項與參數: -d :刪除訊息當中的 SET1 這個字串; -s :取代掉重復的字符![dmtsai@study ~]# col [-xb] 選項與參數: -x :將 tab 鍵轉換成對等的空白鍵[dmtsai@study ~]# join [-ti12] file1 file2 選項與參數: -t :join 默認以空白字符分隔數據,并且比對“第一個字段”的數據, 如果兩個文件相同,則將兩筆數據聯成一行,且第一個字段放在第一個! -i :忽略大小寫的差異; -1 :這個是數字的 1 ,代表“第一個文件要用那個字段來分析”的意思; -2 :代表“第二個文件要用那個字段來分析”的意思。[dmtsai@study ~]# paste [-d] file1 file2 選項與參數: -d :后面可以接分隔字符。默認是以 [tab] 來分隔的! - :如果 file 部分寫成 - ,表示來自 standard input 的數據的意思。[dmtsai@study ~]# expand [-t] file 選項與參數: -t :后面可以接數字。一般來說,一個 tab 按鍵可以用 8 個空白鍵取代。 我們也可以自行定義一個 [tab] 按鍵代表多少個字符呢![dmtsai@study ~]# split [-bl] file PREFIX 選項與參數: -b :后面可接欲分區成的文件大小,可加單位,例如 b, k, m 等; -l :以行數來進行分區。 PREFIX :代表前置字符的意思,可作為分區文件的前導文字。15.管線命令(pipe)
那么如果這群數據必需要經過幾道手續之后才能得到我們所想要的格式,應該如何來設置? 這就牽涉到管線命令的問題了 (pipe) ,管線命令使用的是“ | ”這個界定符號! 其實這個管線命令“ | ”僅能處理經由前面一個指令傳來的正確信息,也就是 standard output 的信息,對于 stdandard error 并沒有直接處理的能力。那么整體的管線命令可以使用下圖表示16.參數代換: xargs
# 很多指令其實并不支持管線命令,可使用xargs以指引stdin [dmtsai@study ~]# xargs [-0epn] command 選項與參數: -0 :如果輸入的 stdin 含有特殊字符,例如 `, \, 空白鍵等等字符時,這個 -0 參數 可以將他還原成一般字符。這個參數可以用于特殊狀態喔! -e :這個是 EOF (end of file) 的意思。后面可以接一個字串,當 xargs 分析到這個字串時, 就會停止繼續工作! -p :在執行每個指令的 argument 時,都會詢問使用者的意思; -n :后面接次數,每次 command 指令執行時,要使用幾個參數的意思。 當 xargs 后面沒有接任何的指令時,默認是以 echo 來進行輸出喔! ps -ef | grep java | grep -v "grep" | awk '{print $2}' | xargs kill17.關于減號的用途:-
[root@localhost ddd]# tar zcvf - test.txt | tar zxvf - mysql #將test.txt打包,但是不是記錄到文件 而是傳送到stdout;經過管線之后 把tar zcvf - test.txt傳送給tar zxvf -;這里的-,就是取用前面一個指令的stdout18.數據流重導向
(1)指令執行過程的數據傳輸情況
(2)standard output 與 standard error output
標準輸出指的是“指令執行所回傳的正確的訊息”,而標準錯誤輸出可理解為“指令執行失敗后,所回傳的錯誤訊息”;用數據重導向可以將standard output (簡稱 stdout) 與 standard error output (簡稱 stderr)分別傳送到其他的文件或設備 1. 標準輸入 (stdin) :代碼為 0 ,使用 < 或 << ; 2. 標準輸出 (stdout):代碼為 1 ,使用 > 或 >> ; 3. 標準錯誤輸出(stderr):代碼為 2 ,使用 2> 或 2>> ;ll / > ~/rootfile 將根目錄下的目錄寫進rootfile這個文件;或者用1>1> :以覆蓋的方法將“正確的數據”輸出到指定的文件或設備上; 1>>:以累加的方法將“正確的數據”輸出到指定的文件或設備上; 2> :以覆蓋的方法將“錯誤的數據”輸出到指定的文件或設備上; 2>>:以累加的方法將“錯誤的數據”輸出到指定的文件或設備上; #將stdout和stderr存到不同的文件;屏幕不會打印信息 find /home -name .bashrc > list_right 2> list_error(3)/dev/null設備和特殊寫法
#只顯示正確信息 find /home -name .bashrc 2> /dev/null#怎么把正確和錯誤信息同時寫進文件 find /home -name .bashrc >list 2>list #錯誤 可能會交叉寫入該文件內,造成次序的錯亂,雖文件會產生 但是里面的數據排列是亂的 find /home -name .bashrc >list 2>&1 #正確 對于空文件就>/dev/null 2>&1 前半部分正常輸出,2表示stderr 表示2的輸出重定向等同于1 find /home -name .bashrc >list #正確#>/dev/null 2>&1 將錯誤信息重定向到1 ;; 1>&2將正確信息重定向到2(4)standard input <和<<
將原本由鍵盤輸入的數據,改由文件內容來取代#由于加入>在cat后,所以那個catfile會被主動的創建,文件內容即鍵盤輸入;使用C+D結束;也可以用cat >>catfile進行鍵盤累加 cat > catfile #用stdin取代鍵盤的輸入以創建新文件的簡單流程 cat > catfile < ~/.bashrc #將bashrc的文件內容寫進catfile#用cat直接由鍵盤寫入catfile中, 且當由鍵盤輸入eof時,結束輸入 cat > catfile << "eof" #<<可以終止輸入二、正則表達式(Regular Expression)與文件格式化處理
揭開正則表達式的神秘面紗
正則表達式30分鐘入門教程
正則在線校驗1 正則在線校驗2(多使用這兩個網址練習)
1.grep的一些進階
-c 統計關鍵字次數;也可以用|wc -l代替 -v 排除相關行 -w 只顯示全字符合的列 -i 忽略字符大小寫的差別 -o 只輸出文件中匹配到的部分 -n 顯示列號 --color 關鍵字顯示顏色;實際grep已經用alias設置為‘grep --color=auto’2.正則相關
* 利用[]搜索集合字符 * 利用''搜尋特定字符 #eg: grep -n '[^g]oo' regular_express.txt ==搜尋oo且oo前面沒有g;但比如gooole 是符合搜索條件的grep -n '[^a-z]oo' regular_express.txt * 行首與行尾字符 ^ $ ^ -1.表示否定[^a]表示“匹配除了a的任意字符”。[^a-zA-Z0-9]表示“找到一個非字母也非數字的字符”。[\^abc]表示“找到一個插入符或者a或者b或者c”。用[/abc]也Ok 但是需避免轉義字符?-2.表示限定開頭/[(^\s+)(\s+$)]/g(^cat)$(^cat$)^(cat)$^(cat$) #eg:grep -n '^$' filename ==打印空白行 #eg:grep -v '#' /etc/rsyslog.conf | grep -v '^$' * 任意一個字符. 與重復字符*(!!!和萬用字符的含義不一樣) #text: "Open Source" is a good mechanism to develop programs. #重點:“o”代表的是:“擁有空字符或一個 o 以上的字符”,因此'o*'會把打印所有字符;oo*:第一個肯定存在,第二個是可有可無的多個o,所有凡是含有o,oo,ooo等都會 打印出來 #eg:grep -n 'g..d' regular_express.txt ==搜索g和d之間是兩個字符條件的 #eg:grep -n 'g.*g' regular_express.txt ==.* 就代表零個或多個任意字符,匹配開頭是g結尾也是g的字符串 #eg:grep -n 'g*g' regular_express.txt ==代表匹配一個以及多個連續的g * 限定連續 RE 字符范圍 {} -1.若為 {n} 則是連續n個的前一個RE字符-2.若是 {n,} 則是連續n個以上的前一個RE字符 #{ 與 } 的符號在 shell 是有特殊意義(命令塊)的,因此, 我們必須要使用跳脫字符 \ 來讓他失去特殊意義才行 也適用其他特殊字符 #eg:grep -n 'go\{2,5\}g' regular_express.txt ==g后2到5個o,再接一個g的字符串 #eg:grep -n 'go\{2,\}g' regular_express.txt ==g后2個及以上的o,再接一個g的字符串3.sed工具
[dmtsai@study ~]$ sed [-nefr] [動作] 選項與參數: -n :使用安靜(silent)模式。在一般 sed 的用法中,所有來自 STDIN 的數據一般都會被列出到屏幕上。但如果加上 -n 參數后,則只有經過 sed 特殊處理的那一行(或者動作)才會被列出來。 -e :直接在命令行界面上進行 sed 的動作編輯; -f :直接將 sed 的動作寫在一個文件內, -f filename 則可以執行 filename 內的 sed 動作; -r :sed 的動作支持的是延伸型正則表達式的語法。(默認是基礎正則表達式語法) -i :直接修改讀取的文件內容,而不是由屏幕輸出。 動作說明: [n1[,n2]]function n1,n2 :不見得會存在,一般代表“選擇進行動作的行數”,舉例來說,如果我的動作是需要在 10 到 20 行之間進行的,則“ 10,20[動作行為] ” function 有下面這些咚咚: a :新增, a 的后面可以接字串,而這些字串會在新的一行出現(目前的下一行)~ c :取代, c 的后面可以接字串,這些字串可以取代 n1,n2 之間的行! d :刪除,因為是刪除啊,所以 d 后面通常不接任何咚咚; i :插入, i 的后面可以接字串,而這些字串會在新的一行出現(目前的上一行); p :打印,亦即將某個選擇的數據印出。通常 p 會與參數 sed -n 一起運行~ s :取代,可以直接進行取代的工作哩!通常這個 s 的動作可以搭配正則表達式* 以行為單位的新增/刪除功能 #eg: [root@localhost ddd]# nl /etc/passwd | sed '2,5d' =='2,3d'刪除2-3行;'2d':刪除第二行;'3,$d':刪除3到最后一行1 root:x:0:0:root:/root:/bin/bash6 sync:x:5:0:sync:/sbin:/bin/sync #eg: [root@localhost ddd]# nl /etc/passwd | sed '2a drink tea' ==在第二行后加打印;如果是第二行之前用''2i drink tea'1 root:x:0:0:root:/root:/bin/bash2 bin:x:1:1:bin:/bin:/sbin/nologin drink tea3 daemon:x:2:2:daemon:/sbin:/sbin/nologin #eg: [root@localhost ddd]# nl /etc/passwd | sed '2a line1\nline2' ==在第二行之后連續打印兩行數據,可以用\n或者\+enter;如果想新增line1\nline2 就加跳脫字符'2a line1\\nline2'1 root:x:0:0:root:/root:/bin/bash2 bin:x:1:1:bin:/bin:/sbin/nologin line1 line2* 以行為單位的取代與顯示功能 #eg: [root@localhost ddd]# nl /etc/passwd | sed '2c No line2 number' ==替代第二行數據1 root:x:0:0:root:/root:/bin/bash No line2 number #eg: [root@localhost ddd]# nl /etc/passwd | sed -n '2,3p' ==打印2-3行,也可以用head -n 3 /etc/passwd| tail -n 2;另使用-n2 bin:x:1:1:bin:/bin:/sbin/nologin3 daemon:x:2:2:daemon:/sbin:/sbin/nologin* 部分數據的搜索并取代的功能 #sed 's/要被取代的字串/新的字串/g' #eg: #sed 's/^.*inet //g' ==刪除inet以及之前的打印 #sed 's/#.*$//g' ==刪除#及其注釋的內容 #開始到行尾($) #sed '/^$/d' ==刪除空白行,用/轉義 #sed -i 's/\.$/\!/g' ==把每一行行尾若為.則換成!在a動作增加的這種情況下 $表示最后一行。s替換的這種模式下,用的是正則。$表示行尾。 #sed -i '$a # This is a test' ==最后一行加上打印;;首行必須有數據 才能插入;; 也可以echo "text" >> file4.延伸正則表達式
#eg:去除空白行和首行為#的行列-1.grep -v '^$' regular_express.txt | grep -v '^#' ==管線命令-2.egrep -v '^$|^#' regular_express.txt ==延伸型的正則表達式;egrep也可以使用grep -E替代- 延伸型正則表達式的幾個特殊符號
5.文件的格式化與相關處理
不需要重新以vim去編輯,通過數據流重導向配合下面介紹的printf功能,以及awk指令
5.1格式化打印:printf
[dmtsai@study ~]$ printf '打印格式' 實際內容 選項與參數: 關于格式方面的幾個特殊樣式: \a 警告聲音輸出 \b 倒退鍵(backspace) \f 清除屏幕 (form feed) \n 輸出新的一行 \r 亦即 Enter 按鍵 \t 水平的 [tab] 按鍵 \v 垂直的 [tab] 按鍵 \xNN NN 為兩位數的數字,可以轉換數字成為字符。 關于 C 程序語言內,常見的變量格式 %ns 那個 n 是數字, s 代表 string ,亦即多少個字符; %ni 那個 n 是數字, i 代表 integer ,亦即多少整數碼數; %N.nf 那個 n 與 N 都是數字, f 代表 floating (浮點),如果有小數碼數, 假設我共要十個位數,但小數點有兩位,即為 %10.2f 啰!- eg:參考此鏈接
5.2 awk
#awk運行模式:awk '條件類型1{動作1} 條件類型2{動作2} ...' filename print、printf,print會自動換行不用\n #awk處理流程:awk 的處理流程是:-1. 讀入第一行,并將第一行的數據填入 $0, $1, $2.... 等變量當中;-2. 依據 "條件類型" 的限制,判斷是否需要進行后面的 "動作";-3. 做完所有的動作與條件類型;-4. 若還有后續的“行”的數據,則重復上面 1~3 的步驟,直到所有的數據都讀完為止。 #awk變量名稱:-1.NF:每一行($0)擁有的字段總數;$NF表示打印最后一個字段的值-2.NR:目前 awk 所處理的是“第幾行”數據-3.FS:目前的分隔字符,默認是空白鍵 #awk邏輯運算符:> 大于 < 小于>= 大于等于 <= 小于等于== 等于 !== 不等于 #eg: [root@localhost ddd]# last -n 2 root pts/0 192.168.15.1 Sun Apr 24 21:30 still logged in root pts/1 192.168.15.1 Sat Apr 23 22:12 - 19:45 (21:33) [root@localhost ddd]# last -n 2 | awk '{print $1 "\t" $3}' ==出去第一、三列 中間用tab符 每一行用\n換行;$n(n!=0)代表第n列 $0代表每行 root 192.168.15.1 root 192.168.15.1 #eg:awk '{ print NR "\t" NF "\t" $0}' /etc/passwd ==輸出每行的行號,每行的列數,對應的完整行內容; #eg:cat /etc/passwd | awk 'BEGIN {FS=":"} $3<10 {print $1 "\t" $3}' ==用:為分隔符,第三列值<10,打印第一、三列;因為FS僅能在第二行及之后生效 所 以預設了awk的變量 使用BEGIN關鍵字 #eg: #所有 awk 的動作,亦即在 {} 內的動作,如果有需要多個指令輔助時,可利用分號“;”間隔 [root@localhost ddd]# cat pay.txt Name 1st 2nd 3th VBird 23000 24000 25000 DMTsai 21000 20000 23000 Bird2 43000 42000 41000 [root@localhost ddd]# cat pay.txt | awk 'NR==1{printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total" } ; NR>=2{total = $2 + $3 + $4 ; printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}' Name 1st 2nd 3th TotalVBird 23000 24000 25000 72000.00DMTsai 21000 20000 23000 64000.00Bird2 43000 42000 41000 126000.00 [root@localhost ddd]# cat pay.txt | awk '{if(NR==1) printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total"} ; NR>=2{total = $2 + $3 + $4 ; printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}' ==awk也支持if語句Name 1st 2nd 3th TotalVBird 23000 24000 25000 72000.00DMTsai 21000 20000 23000 64000.00Bird2 43000 42000 41000 126000.006.文件比對工具
1.diff:以行為單位比對,通常用在同一文件的(或軟件)的新舊版本差異上,也可以用做目錄的比對;可以把新舊的版本差異 制作為補丁文件,再由補丁文件更新舊文件即可;可以友echo $?輸出 2.cmp:主要是以字節為單位比對 3.patch:版本的更新與還原 與diff一起使用三、學習Shell Scripts
1.What is Shell Scripts
將一些 shell 的語法與指令(含外部指令)寫在里面, 搭配正則表達式、管線命令與數據流重導向等功能,以達到我們所想要的處理目的。關于init(SystemV)和Systemd的介紹
關于換行符的介紹
1.關于編碼:Dos和Windows采用回車+換行CR/LF表示下一行;而UNIX/Linux采用換行符LF表示下一行 2.scripts添加信息:功能、版本、作者信息、修改記錄、需要的環境變量;最好使用vim 3.調試:bash -x [filename] 4.超出表達式遞歸:https://stackoverflow.com/questions/30404863/expression-recursion-level-exceeded 5.filename=$ {fileuser:-"filename"} 若變量fileuser為空 ,則返回"filename".若變量 fileuser 有值,則返回其當前值;以確保變量一直有值 6.善于使用$? || 以及&&進行判斷前一個指令回傳至對于后一個指令是否要進行的依據;也可以使用test指令 #根據日期創建文件 #!/usr/bin/sh read -p "please input filename: " fileuser filename=${fileuser:-"filename"} #檢查fileuser是否存在 #獲取日期 date1=$(date --date='1 days ago' +%Y%m%d) #一天前 date0=$(date +%Y%m%d) #今天 #配置文件名 file1=${filename}_${date1} file0=${filename}_${date0} #創建文件 touch "${file1}.log" touch "${file0}.log" #數值運算;可以用$((運算式))來定義運算式; #!/usr/bin/sh read -p "input first number: " first_num read -p "input second number: " sec_num total=$((first_num * sec_num)) echo -e "${first_num}*${sec_num}=${total}" #另計算含有小數的數據時,可以用bc協助 比如echo "2.2+3.4"|bc2.script的執行差異
-
利用bash(sh)來下達腳本時,改script是在子程序的bash內執行的,會使用一個新的bash環境;所以是script內的變量在bash環境下無效
-
利用source執行腳本,在父程序中執行,script中的變量會在bash中生效;source ~/.filename.sh
3.利用test指令的測試功能
主要進行數值、字符串和文件三個方面的檢測
1.數值檢測
#eg: test 1 -eq 2 && echo "yes" || echo "no" -eq:值 1 等于值 2 -ge : 值 1 大于或等于值 2 -gt : 值 1 大于值 2 -le : 值 1 小于或等于值 2 -lt : 值 1 小于值 2 -ne : 值 1 不等于值 22.比較文本
#eg: test "string1" = "string2" && echo "yes" || echo "no" ==判斷兩個字符串是否相等 #eg: test -n "string1" && echo "yes" || echo "no" ==判斷字符串長度是否大于0 ==:字符串 1 匹配字符串 2;;等號兩邊要有空格!!! != : 字符串 1 與字符串 2 不匹配 -n:字符串長度大于0 -z:字符串長度等于 03.比較文件
-ef:文件具有相同的設備和 inode 編號(它們是同一個文件) -nt : 第一個文件比第二個文件新 -ot:第一個文件比第二個文件舊 -d:文件存在并且是目錄(directory) -e : 文件存在 -f : 文件存在并且是文件(file) -r:文件存在且可讀 -s:文件存在且大小大于零 -w:文件存在且可寫 -x:文件存在且可執行`優化1:[ "$a" == "$b" ] 優化 [ x"$a" == x"$b" ]:這種辦法避免了$b為空的情況下 bash報錯 `優化2:[ x"$1" == x"1" ] 避免參數為空bash版本不兼容報錯;但是也可以[ "$1" == ""]4.多個條件判斷
# -a表示and,-o表示or #eg:test 4 -eq 4 -a "string1" == "string2" && echo "yes" || echo "no" == -a條件同時滿足 #eg: test 4 -eq 4 -o "string1" == "string2" && echo "yes" || echo "no" == -o條件之一滿足 #檢測文件是否存在 #!/usr/bin/sh # Program: # User input a filename, program will check the flowing: # 1.) exist? 2.) file/directory? 3.) file permissions # 1\. 讓使用者輸入文件名,并且判斷使用者是否真的有輸入字串? echo -e "Please input a filename, I will check the filename's type and permission. \n\n" read -p "Input a filename : " filename test -z ${filename} && echo "You MUST input a filename." && exit 0 #判斷字符串長度是否為0 或用[ -z "${filename}"" ]判斷 # 2\. 判斷文件是否存在?若不存在則顯示訊息并結束腳本 test ! -e ${filename} && echo "The filename '${filename}' DO NOT exist" && exit 0 # 3\. 開始判斷文件類型與屬性 test -f ${filename} && filetype="regulare file" test -d ${filename} && filetype="directory" test -r ${filename} && perm="readable" test -w ${filename} && perm="${perm} writable" test -x ${filename} && perm="${perm} executable" # 4\. 開始輸出信息! echo "The filename: ${filename} is a ${filetype}" echo "And the permissions for you are : ${perm}"5.利用判斷符號[]
- 必須要注意中括號的兩端需要有空白字符來分隔
- 中括號內字符需要使用雙引號
4.Shell Scripts的默認變量 ($0,$1…)
/path/to/scriptname opt1 opt2 opt3 opt4$0 $1 $2 $3 $4 $0代表腳本文件名,接著的第一個參數就是$1 $# :代表后接的參數“個數”,以上表為例這里顯示為4; $@ :代表“ "$1" "$2" "$3" "$4" ”之意,每個變量是獨立的(用雙引號括起來);和$*不同 記憶$@即可 $* :代表“ "$1<u>c</u>$2<u>c</u>$3<u>c</u>$4" ”,其中 <u>c</u> 為分隔字符,默認為空白鍵, 所以本例中代表“ "$1 $2 $3 $4" ”之意。 # shift:造成參數變量號碼偏移 #!/bin/bash echo "the script name is $0" #打印文件名 [ "$#" -lt 2 ] && echo "less than 2" && exit 0 #利用[]判斷 echo "the whole(\$@) is $@" #打印全部參數內容 echo "the 1st parameter(\$1) is $1" #打印第一個參數[root@localhost bin]# sh test.sh a b the script name is test.sh the whole($@) is a b the 1st parameter($1) is a5.條件判斷式
5.1.利用if …then
- 單層、簡單的條件判斷式
- 多重、復雜條件判斷式
5.2.利用case…in…esac判斷
case $變量名稱 in 模式1)command1command2;; #每個類別結尾使用兩個連續的分號來處理 模式2)command1command2;; *) #最后一個變量內容都會用 * 來代表所有其他值command1command2;; esac #!/usr/bin/sh read -p "input a num:" aNum case $aNum in 1) echo 'You select 1';; 2) echo 'You select 2';;*) echo 'You do not select a number between 1 to 4';; esac5.3.利用function功能
#!/usr/bin/sh function printit(){echo -n "ur choice is " } case ${1} in"one")printit; echo ${1} | tr 'a-z' 'A-Z' #調用;轉換大小寫;;*) echo 'over';; esac6.循環loop
6.1 while do done, until do done (不定循環)
while [ "${yn}" != "yes" -a "${yn}" != "YES" ] do read -p "Please input yes/YES to stop this program: " yn doneuntil [ "${yn}" == "yes" -o "${yn}" == "YES" ] do read -p "Please input yes/YES to stop this program: " yn dones=0 # 這是加總的數值變量 i=0 # 這是累計的數值,亦即是 1, 2, 3.... while [ "${i}" != "100" ] do i=$(($i+1)) # 每次 i 都會增加 1 s=$(($s+$i)) # 每次都會加總一次! done6.2 for…in…do…done (固定循環)
for var in con1 con2 con3 ... do 程序段 donefor animal in dog cat elephant do echo "There are ${animal}s.... " done#檢測服務器狀態 #usr/bin/sh network="192.168.15" ping_chk_file=/home/ddd/ping_chk_file_$(date +%Y%m%d).txt [ ! -e "$ping_chk_file" ] && touch ${ping_chk_file} #檢測文件 不存在則創建 #cat /dev/null > ${ping_chk_file} #文件置空 [ ! -s "$ping_chk_file" ] && echo "# ping-check" >> ${ping_chk_file} #文件為空則添加首行 可以為下文的sed -i服務; echo "excuting" for sitenu in $(seq 120 130) #seq 連續 doping -c 1 -w 1 ${network}.${sitenu} >/dev/null && result=0 || result=1 #免除界面打印if [ "$result" = 0 ] ; thenecho "$(date "+%Y-%m-%d %H:%M:%S"): server ${network}.${sitenu} is UP" >> ${ping_chk_file} #方便簡單# sed -i '$a server ${network}.${sitenu} is UP' ${ping_chk_file} #高級,但需要首行有數據才能處理elseecho "$(date "+%Y-%m-%d %H:%M:%S"): server ${network}.${sitenu} is DOWN" >> ${ping_chk_file}# sed -i '$a server ${network}.${sitenu} is DOWN' ${ping_chk_file}fi done#檢測文件權限 #usr/bin/sh read -p "Please input a directory: " dir if [ "${dir}" == "" -o ! -d "${dir}" ] ; then #經常用吧 echo "The ${dir} is NOT exist in your system." exit 1 fi # 2\. 開始測試文件啰~ filelist=$(ls ${dir}) # 列出所有在該目錄下的文件名稱;注意格式 引用賦值 for filename in ${filelist} do perm="" test -r "${dir}/${filename}" && perm="${perm} readable" test -w "${dir}/${filename}" && perm="${perm} writable" test -x "${dir}/${filename}" && perm="${perm} executable" echo "The file ${dir}/${filename}'s permission is ${perm} " done6.5 for…do…done 的數值處理
for (( 初始值; 限制值; 執行步階 )) do 程序段 done 這種語法適合于數值方式的運算當中,在 for 后面的括號內的三串內容意義為: 初始值:某個變量在循環當中的起始值,直接以類似 i=1 設置好; 限制值:當變量的值在這個限制值的范圍內,就繼續進行循環。例如 i<=100; 執行步階:每作一次循環時,變量的變化量。例如 i=i+1。#usr/bin/sh read -p "input a num " nu s=0 for((i=1; i<=${nu}; i++)) dos=$((${s}+${i})) done echo "sum is ${s}"7.shell script的追蹤與debug
sh [-nvx] scripts.sh 選項與參數: -n :不要執行 script,僅查詢語法的問題; -v :再執行 sccript 前,先將 scripts 的內容輸出到屏幕上; -x :將使用到的 script 內容顯示到屏幕上,這是很有用的參數!四、補充
1.打印進度條
#!/bin/sh b='' for ((i=0;$i<=100;i+=2)) doprintf "progress:[%-50s]%s%%\r" $b $i #[]內左靠齊50個$b,%s給$i,%%轉義打印%,\r收到回車再換行sleep 0.02b=#$b done echo2.文件描述符(參考第一章18小節)
用途
/dev/null 是一個特殊的設備文件,它丟棄一切寫入其中的數據 可以將它 視為一個黑洞, 它等效于只寫文件, 寫入其中的所有內容都會消失, 嘗試從中讀取或輸出不會有任何結果,同樣,/dev/null 在命令行和腳本中都非常有用/dev/null通常被用于丟棄不需要的輸出流,或作為用于輸入流的空文件,這些操作通常由重定向完成,任何你想丟棄的數據都可以寫入其中
丟棄標準輸出、丟棄標準錯誤輸出
在寫shell腳本的時候,只想通過命令的結果執行后面的邏輯,而不想命令執行過程中有一大堆中間結果輸出,這時候可以把命令執行過程中的輸入全部寫入 /dev/null
#丟棄標準輸出 #!/bin/bash command -v $1 >/dev/null #command -v 命令名 是查找指定命令名的命令是否存在,如果存在,輸出指定命令名的路徑,否則,不做任何輸出;執行./a.sh top 則不打印路徑 if [[ $? -eq 0 ]]; thenecho "command $1 exist..." elseecho "command $1 not exist..." fi#丟棄標準錯誤輸出 #!/bin/bash rm $1 >/dev/null 2>$1 #或用2>/dev/null替代 丟棄標準錯誤輸出清空文件內容
cat /dev/null > t.txt
3.進程檢測
#!/bin/bash # 如果此機器不存在這個,則配置為1 aboss5_flag=0 aboss2_flag=1 tomcat_flag=0 mycat_flag=0 # procmgr start procmgr_ids=`ps -ef | grep procmgr | grep -v "grep" | awk '{print $2}'` for id in $procmgr_ids dopathDir=`ls -al /proc/$id/cwd | awk '{print $NF}'` #取出id echo [$id]:[$pathDir]if [[ "$pathDir" == *"aboss5"* ]]; then #兩層[]為匹配正則*aboss5_flag=1echo "[NOTE] aboss5 procmgr is already started."elif [[ "$pathDir" == *"aboss2"* ]]; thenaboss2_flag=1echo "[NOTE] aboss2 procmgr is already started."fi done4.關于雙方括號
雙方括號的用法說明
- 支持字符匹配
-
支持&& -a -o多個條件連接處理
if [[ "a" == "a" && 2 -gt1 ]]
5.注釋
1. #單行注釋 2. :`多行注釋` 3. << BLOCK多行注釋BLOCK6.引號
對于打印文本 單引號和雙引號沒有區別;打印輸出一個已定義的變量,則需要使用雙引號
#!/usr/bin/sh read -sp "num:" num #-s支持靜默不在界面打印 echo -e "\\n $num" #-e支持轉義字符7.關于日期格式化
[root@localhost scripts]# date +%Y-%m-%d" "%H:%M:%S 2022-05-06 00:14:42 +%Y 年 2022m 月 01d 日 01H 時 二十四小時制M 分 S 秒8.sleep
sleep 1d 2h 3m 30s 默認是秒 也可用作定時執行 不規范總結
以上是生活随笔為你收集整理的Linux-bash笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: allure报告的定制化
- 下一篇: Python 中的 dbm 模块