目錄
本文爲慕課網Tony老師視頻筆記,Tony老師的課通俗易懂,幽默風趣,Linux入門或鞏固基礎的話,推薦看一下!https://www.imooc.com/u/279399/courses?sort=publish
一、Shell編程之變量
Shell與其他語言對比:
1、php和java等語言主要實現功能
2、Shell是簡化管理操作
變量概念:
裏面存儲的內容或者值是可以改變的量,變量方便在程序中對值進行傳遞替換和調用
變量命名規則:
1、變量名可以有字母下劃線數字組成,但不能以數字打頭
2、變量名長度不能超過255個字符
3、變量名在有效範圍內必須是唯一的
4、在Bash中變量的默認類型是字符串型
變量的分類:
1、用戶自定義變量:變量是自定義的
2、環境變量:這種變量中主要保存的是和系統操作環境相關的數據,
變量可以自定義,但是對系統生效的環境變量名和變量作用是固定的
3、預定義變量:是Bash中已經定義好的變量,變量名不能自定義,變量作用也是固定的
4、位置參數變量(是預定義變量的一種):這種變量主要是用來向腳本中傳遞參數和數據的,
變量名不能自定義,變量作用是固定的
用戶自定義變量
1、Shell中定義變量的時候等號兩邊不能加空格,否則系統會認爲這條語句是一條命令空格後面的是參數
2、如果變量值中有空格需要用雙引號或單引號括起來,
雙引號括起來的字符串中一些特殊符號是起作用的而單引號括起來的則是一個單純的符號
3、如果需要調用變量需要在變量名之前加$,定義變量的話不用加$
4、變量的疊加(類似於java中兩個字符串相加):x=123 x="$x"456 或 x=${x}456 echo $x 123456
5、set命令:查詢系統下所有已經生效的變量,set -u 默認當變量不存在時輸出變量爲空白,使用該命令之後會明確提示變量不 存在
unset+變量名 刪除變量,注意變量名之前不加$
6、自定義變量是局部變量只在當前bash有效
環境變量
1、環境變量是全局變量
2、對系統生效的環境變量名和變量作用是固定的
3、定義環境變量:export 變量名=變量值
4、env命令:查看環境變量,刪除也是使用unset,不過刪除的時候要到定義該變量的bash中刪除
5、常用環境變量
PATH:系統搜索命令的路徑
PS1:命令提示符(root@locahost)設置
HOSTNAME:主機名
SHELL:當前的shell
TERM:終端環境
HISTSIZE:歷史命令條數
SSH_CLIENT:當前操作環境使用ssh連接的話,這裏記錄客戶端ip
SSH_TTY:ssh連接終端時pts/1
USER:當前登錄的用戶
6、增加環境變量:PATH="$PATH":/root/bin.sh
7、locale命令:查詢當前系統語系,LANG:定義系統主語系的變量,LC_ALL:定義整體語系的變量
8、/etc/sysconfig/i18n 保存着默認語系(下次開機所加載的語系)
預定義變量
1、$? 最後一次執行的命令的返回狀態,如果這個變量的值爲0,證明上一個命令正確執行,如果值爲非0證明上一個命令執行不 正確
2、$$ 當前進程的進程號(PID)
3、$! 後臺運行的最後一個進程的進程號(PID)
位置參數變量
1、$n n爲數字,$0代表命令本身,$1-$9代表第一到第九個參數,十以上的參數需要用大括號包含,如${10}
2、$* 這個變量代表命令行中所有的參數,$*把所有的參數看成一個整體
3、$@ 這個變量也代表命令行中所有的參數,不過$@把每個參數區分對待
4、$# 這個變量代表命令行中所有參數的個數
二、Shell編程之運算符
進行數值運算的方式如下:
declare
declare:聲明變量類型
declare[+/-][選項][變量名]
-:給變量設定類型屬性
+:取消變量的類型屬性
-a:將變量聲明爲數組型
-i:將變量聲明爲整型
-x:將變量聲明爲環境變量(export其實就是調用這條命令)
-r:將變量聲明爲只讀變量(設置了只讀之後不能取消不能刪除,慎用)
-p:顯示指定變量的被聲明的類型
expr或let
dd=$(expr $aa + $bb)
dd的值是aa和bb的和。注意+號左右兩邊必須有空格
$((運算式))或$[運算式]
dd=$(($aa+$bb))
dd=$[$aa+$bb]
變量測試
比如x=${y-新增},作用是用x值推測y的值,在腳本優化時使用,變量測試表見百度
三、Shell編程之環境變量配置文件
環境變量配置文件簡介
環境變量配置文件中主要是定義對系統環境生效的系統默認環境變量,如PATH等
source命令
命令和source命令作用相同
修改配置文件之後必須註銷重新登錄才生效,使用source命令可以不重新登錄
常用的環境變量配置文件
對所有用戶起作用:
/etc/profile(歷史命令條數在這設置)
/etc/profile.d/*.sh
/etc/bashrc(命令別名在這設置)
對當前用戶起作用:
~/.bash_profile
~/.bashrc
用戶登錄時文件調用順序
/etc/profile -- ~/.bash_profile -- ~/.bashrc -- /etc/bashrc -- 命令提示符
| | (root用戶切換用戶時不需要輸入密碼走這條路,比起完整的線路少加載了/etc/profile, | | ~/.bash_profile,~/.bashrc)
/etc/profile.d/*.sh-----------------------
|
/etc/profile.d/lang.sh -- /etc/sysconfig/i18h(默認語系)
~/.bash_logout:註銷時執行的環境變量文件
umask命令
umask:查看系統默認權限
注意:
1、文件最高權限爲666(文件不能一建立就可以執行,需要後續賦予執行權限)
2、目錄最高權限爲777
3、權限不能使用數字進行換算,而必須使用字母
4、umask定義的權限,是系統默認權限中準備丟棄的權限
歡迎信息
本地終端歡迎信息/etc/issue:
支持轉移字符比如:/l 顯示登錄的終端號,/m 顯示硬件體系結構
遠程終端歡迎信息:/etc/issue.net
轉義符在/etc/issue.net文件中不能使用
是否顯示此歡迎信息,由ssh的配置文件/etc/ssh/ssd_config決定
加入"Banner /etc/issue.net"行才能顯示(需要重啓SSH服務)
登錄後歡迎信息:/etc/motd
不管是本地終端登錄還是遠程登錄,都可以顯示此歡迎信息
四、Shell編程之正則表達式
正則表達式:主要用於字符串的分割、匹配、查找和替換(主要是模糊匹配)
通配符
*:匹配任意內容
?:匹配任意一個內容
[]:匹配中括號中的一個字符
正則表達式與通配符
正則表達式用來在文件中匹配符合條件的字符串,正則是包含匹配。grep、awk、sed等命令可以支持正則表達式
通配符用來匹配符合條件的文件名,通配符是完全匹配。ls、find、cp這些命令不支持正則表達式,所以只能用shell自帶的通配符來進行匹配了
基礎正則表達式
*:前一個字符匹配0次或任意多次
.:匹配除了換行符外任意一個字符
^:匹配行首。例如:^hello會匹配以hello開頭的行
$:匹配行尾。例如hello$會匹配以hello結尾的行
[]:匹配中括號中指定的任意一個字符,只匹配一個字符。
例如:[aoeiu]匹配任意一個元音字母,[0-9]匹配任意一位數字,[a-z][0-9]匹配小寫字母和一位數字構成的兩位字符
[^]:匹配除中括號中的字符以外的任意一個字符。
例如:[^0-9]匹配任意一位非數字字符,[^a-z]表示任意一位非小寫字母
\:轉義符。用於將特殊符號的含義取消
\{n\}:表示其前面的字符恰好出現n次。例如:[0-9]\{4\}匹配4位數字,[1][3-8][0-9]\{9\}匹配手機號碼
\{n,\}:表示其前面的字符出現不小於n次。例如:[0-9]\{2,\}表示2位及2位以上的數字
\{n,m\}:表示其前面的字符至少出現n次,最多出現m次。例如:[a-z]\{6,8\}匹配6-8位的小寫字母
字符截取命令
cut[選項]文件名:字段提取命令
-f 列號:提取第幾列
-d 分隔符:按照指定分隔符分割列
printf '輸出類型輸出格式' 輸出內容
輸出類型:
%ns:輸出字符串。n是數字指代輸出幾個字符
%ni:輸出整數。n是數字指代輸出幾個數字
%m.nf:輸出浮點數。m和n是數字,指代輸出的整數位數和小數位數,如%8.2f
代表輸出8位數,其中2位是小數,6位是整數
輸出格式:
/a:輸出警告聲音
/b:輸出退格鍵,也就是BackSpace鍵
/f:清除屏幕
/n:換行
/r:回車,也就是Enter鍵
/t:水平輸出退格鍵,也就是Tab鍵
/v:垂直輸出退格鍵,也就是Tab鍵
printf '%s' $(cat student.txt)
不調整輸出格式
printf '%s\t%s\t%s\t%s\n' $(cat student.txt)
調整格式輸出
在awk命令的輸出中支持print和printf命令(和C語言中正好相反)
print:print會在每個輸出之後自動加入一個換行符(Linux默認沒有print命令)
printf:printf是標準的格式輸出命令,並不會自動加入換行符,如果需要換行,需要手工加入換行符
awk '條件1{動作1}條件2{動作2}...' 文件名:字段提取命令(默認用空格或者製表符作爲分隔符)
條件(Pattern)
一般使用關係表達式作爲條件
x>10判斷變量 x是否大於10
x>=10大於等於
x<=10小於等於
動作(Action)
格式化輸出
流程控制語句
無條件:
awk '{printf $2 "\t" $4 "\n"}' student.txt
截取student文件的第二列和第四列並以\t爲分隔符,\n爲換行符
注意,這裏printf命令後面需要用單引號括起來,但是awk命令已經用了單引號,所以printf命令的轉義字符用雙引號括起來
df -h | awk '{print $1 "\t" $3}'
截取磁盤分區信息的第一行和第三行並以\t爲分隔符
df -h | grep "dev/sda5" | awk '{print $5}'
截取根分區的磁盤使用百分比
有條件:
awk 'BEGIN{printf "This is a transcript \n"}{printf $2 "\t" $4 "\n"}' student.txt
截取student文件中的第二列和第四列,在輸出的時候先輸出This is...,同理也有END
cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN{FS=":"}{printf $1 "\t" $3 "\n"}'
指定分隔符爲冒號
cat student.txt | grep -v Name | awk '$4>=70{printf $2 "\n"}'
讀取student文件中除了包含Name行的數據,如果成績大於等於70打印學生名字
sed命令:主要用於對數據進行選取、替換、刪除、新增
sed[選項] '[動作]' 文件名
選項:
-n:一般sed命令把所有的數據都輸出到屏幕,如果加入此選項則只會把經過sed命令處理的行輸出到屏幕
-e:允許對輸入數據應用多條sed命令編輯
-i:用sed的修改結果直接修改讀取數據文件,而不是由屏幕輸出
動作:
a:追加,在當前行後添加一行或多行
c:行替換,用c後面的字符串替換原數據行
i:插入,在當前行前插入一行或多行。
d:刪除,刪除指定行
p:打印,輸出指定行
s:字串替換,用一個字符串替換另一個字符串。格式爲“行範圍s/舊字串/新字串/g”(和vim中的替換格式類似)
字符處理命令
排序命令sort
sort[選項]文件名
選項:
-f:忽略大小寫
-n:以數值型進行排序,默認使用字符串型排序
-r:反向排序
-t:指定分隔符,默認分隔符是製表符
-k n[,m]:按照指定的字段範圍排序。從n字段開始,m字段結束(默認到行尾)
統計命令wc
wc[選項名]文件名
選項:
-l:只統計行數
-w:只統計單詞數
-m:只統計字符數
五、Shell編程之條件判斷於流程控制
條件判斷式
兩種判斷格式:
test -e /root/install.log
[-e /root/install.log]
[-d /root] && echo "yes" || echo "no"
第一個判斷命令如果正確執行,則打印"yes",否則打印"no"
文件類型判斷表
文件權限判斷表
兩個文件之間比較
兩個整數之間比較
字符串的判斷
多重條件判斷
單分支if語句
if [[ condition ]]; then
#statements
fi
if語句使用fi結尾,和一般語言使用大括號不同
[ 條件判斷式 ]就是使用test命令判斷,所以中括號和條件判斷式之間必須有空格
then後面跟符合條件之後執行的程序,可以放在[]之後,用";"分割。也可以換行寫入,就不需要";"了
判斷登錄的用戶是否爲root:
test=$(env | grep "USER" | cut -d "=" -f2)
if [ "$test"==root ]; then
echo "Current user is root"
fi
判斷分區使用率:
test=$(df -h | grep sda5 | awk '{print $5}' | cut -d "%" -f 1)
if [ "$test"-ge"90" ]; then
echo "/ is full"
fi
雙分支if語句
if [[ condition ]]; then
#statements
else
#statements
fi
判斷apache是否啓動(注意:該腳本名中不能出現httpd)
這裏grep -v grep是因爲執行grep的時候也會產生一個包含httpd字符的進程需要把它也過濾
同理,如果腳本名中包含httpd關鍵字,那麼執行該腳本的時候test永遠不會爲空,因爲腳本本身也是個進程
test=$(ps aux | grep httpd | grep -v grep)
#截取httpd進程,並把結果賦予變量test
if [[ -n "$test" ]]; then
#如果test的值不爲空
echo "$(data) httpd is ok!" >> /tmp/autostart-acc.log
#否則啓動apache服務
else
/etc/rc.d/init.d/httpd start &> /dev/null
echo "$(data)restart httpd!!" >> /tmp/autostart-acc.log
fi
多分支if語句
if [[ condition ]]; then
#statements
elif [[ condition ]]; then
#statements
elif [[ condition ]]; then
#statements
else
#statements
fi
判斷num是否爲純數字
原理是把num中的數字都替換成空,如果最後結果test爲空,證明num中是純數字
test=$(echo $num | sed 's/[0-9]//g')
判斷用戶輸入的是什麼文件
#接收鍵盤的輸入,並賦予變量file
read -p "Please input a filename: " file
#判斷變量是否爲空
if [[ -z "$file" ]]; then
echo "Error,please input a filename"
exit 1
elif [[ ! -e "$file" ]]; then
#判斷file值是否存在
echo "Your input is not a file!"
exit 2
elif [[ -f "$file" ]]; then
#判斷file的值是否爲普通文件
echo "$file is a regulare file!"
elif [[ -d "$file" ]]; then
#判斷file的值是否爲目錄文件
echo "$file is a directory!"
else
echo "$file is an other file!"
fi
case語句
case $變量名 in
"值1" )
#如果變量的值等於值1,則執行程序1
;;
"值2" )
#如果變量的值等於值2,則執行程序2
;;
...
*)
#如果變量的值都不是以上的值,則執行此程序
esac
for循環
for (( i = 0; i < 10; i++ )); do
#statements
done
for 變量 in 值1 值2 值3...; do
#statements
done
批量添加指定數量的用戶
read -p "Please input user name:" -t 30 name
read -p "Please input the number of users:" -t 30 num
read -p "Please input the password of users:" -t 30 pass
if [[ !-z "$name" -a !-z "$num" -a !-z"$pass" ]]; then
y=$(echo $num | sed 's/[0-9]//g')
if [[ -z $y ]]; then
for (( i = 1; i <= num; i=i+1 )); do
/usr/sbin/useradd $name$i $>/dev/null
echo $pass | /usr/bin/passwd --stdin $name$i $>/dev/null
done
fi
fi
while循環和until循環
while [[ condition ]]; do
#statements
done
#跟while循環相反,當條件判斷不成立就進行循環,成立就終止循環
until [[ condition ]]; do
#statements
done