bash的基礎特性(1):
(1) 命令歷史
history
系統中history環境變量:
HISTSIZE:命令歷史記錄的條數;
HISTFILE:~/.bash_history;
HISTFILESIZE:命令歷史文件記錄歷史的條數;
history -d OFFSET(具體刪除第幾條歷史記錄)
history -c 清空所有歷史記錄
history #: 顯示歷史中最近的#條命令;
history -a: 手動追加當前會話緩衝區的命令歷史至歷史文件中;
調用歷史中的命令:
!#: 重複執行第#條指令;
!!: 執行上一條指令
!string:最近一條以指定字符串開頭的命令
調用上一條命令的最後一個參數:!$
cat /etc/fstab
ls -l !$
控制命令歷史的記錄方式:由環境變量HISTCONTROL來控制
環境變量:HISTCONTROL,有以下的值
ignoredups:忽略重複的命令;注意:連續且相同方爲“重複”
ignorespace:忽略所有以空白開頭的命令;
ignoreboth:ignoredups, ignorespace(即以上兩個都生效);
修改環境變量值的方式:export 變量名="值",只對當前的shell有效。
export HISTCONTROL=“ignorespace”
(2) 命令補全
bash執行命令:
內部命令:
外部命令:bash根據PATH環境變量定義的路徑,自左而右在每個路徑搜尋以給定命令名命名的文件,第一次找到即爲要執行的命令;
直接補全:Tab,用戶給定的字符串只有一條惟一對應的命令;
以用戶給定的字符串爲開頭對應的命令不惟一,則再次Tab會給出列表;
(3) 路徑補全
把用戶給出的字符串當做路徑開頭,並在其指定上級目錄下搜索以指定的字符串開頭的文件名;
如果惟一:則直接補全;
否則:再次Tab,給出列表;
(4) 命令行展開
~: 展開爲用戶的主目錄
~USERNAME:展開爲指定用戶的主目錄
{}:可承載一個以逗號分隔的列表,並將其展開爲多個路徑
/tmp/{a,b} = /tmp/a, /tmp/b
/tmp/{tom,jerry}/hi = /tmp/tom/hi, /tmp/jerry/hi
(5) 命令的執行結果狀態
成功
失敗
bash使用特殊變量$?保存最近一條命令的執行狀態結果:
0:成功
1-255:失敗
程序執行有兩類結果:
程序的返回值;
程序的執行狀態結果;
bash的基礎特性(2):
1、命令別名(alias)
通過alias命令實現:
(1) alias
顯示當前shell進程中所有可用的命令別名;
(2) alias NAME='VALUE':alias cdnet='cd /etc/sysconfig/network-script'
定義別名NAME,執行NAME就相當於執行命令VALUE;
注意:在命令行中定義的別名,僅對當前shell進程有效;如果想永久有效,要定義在配置文件中;
僅對當前用戶:~/.bashrc
對所有用戶有效:/etc/bashrc
Note: 編輯配置給出的新配置不會立即生效,需要使進程重新讀取配置文件(命令行會立即生效,但不會永久有效):
source /path/to/config_file
或者:. /path/to/config_file
撤消別名:unalias
unalias -a 撤銷所有別名信息
unalias name 撤銷具體某個別名
Note: 如果別名同原命令的名稱,則如果要執行原命令,可使用"\COMMAND";
whatis COMMAND 查看命令有哪些章節
2、glob (globbing):實現文件名“通配”
通配符:*, ?, []
(1) *
任意長度的任意字符
a*b:
aab, ab, a123b,
abc
(2) ?
任意單個字符
a?b:
aab
ab, a12b, abc
(3) []
匹配指定範圍內的任意單個字符
[0-9]:
[a-z]:不區分字符大小寫
[A-Z]:僅匹配A-Z中的一個字符
(4) [^]
匹配指定範圍外的任意單個字符
[^0-9]:不包含數字
專用字符集合:
[:digit:]:任意數字,相當於0-9
[[:digit:]]:相當於[0-9]
[:lower:]:任意小寫字母
[:upper:]: 任意大寫字母
[:alpha:]: 任意大小寫字母
[:alnum:]:任意數字或字母
[:space:]:
[:punct:]:標點符號
練習:
1、顯示/var目錄下所有以l開頭,以一個小寫字母結尾,且中間出現至少一位數字的文件或目錄;
# ls -d /var/l*[0-9]*[[:lower:]]
2、顯示/etc目錄下,以任意一位數字開頭,且以非數字結尾的文件或目錄;
# ls -d /etc/[0-9]*[^0-9]
3、顯示/etc/目錄下,以非字母開頭,後面跟了一個字母及其它任意長度任意字符的文件或目錄;
# ls /etc/[^[:alpha:]][[:alpha:]]*
4、複製/etc目錄下,所有以m開頭,以非數字結尾的文件或目錄至/tmp/mageedu目錄中;
# cp -a /etc/m*[^0-9] /tmp/mageedu
5、複製/etc目錄下,所有以.d結尾的文件或目錄至/tmp/magedu.com目錄中;
# cp -a /etc/*.d /tmp/magedu.com
6、複製/etc目錄下,所以有.conf結尾,且以m,n,r,p開頭的文件或目錄至/tmp/mageedu.com目錄中;
# cp -a /etc/[mnrp]*.conf /tmp/mageedu.com
cp -a /etc/{m,n,r,p}*.conf /tmp/mageedu.com
3、bash的快捷鍵
Ctrl+l: 清屏,相當於clear命令;
Ctrl+a:跳轉至命令開始處;
Ctrl+e:跳轉至命令結尾處;
Ctrl+c:取消命令的執行;
Ctrl+u: 刪除命令行首至光標所在處的所有內容;
Ctrl+k: 刪除光標所在處至命令行尾部的所有內容;
4、bash的的I/O重定向及管道
打開的文件都有一個fd: file descriptor (文件描述符)
標準輸入(默認從鍵盤輸入):鍵盤的文件描述符用“0”表示
比如:cat命令,如果不給定參數,會等待鍵盤輸入
標準輸出(默認從顯示器輸出):顯示器的文件描述符用“1”表示
標準錯誤輸出(默認從顯示器輸出):顯示器的文件描述符用“2”表示
I/O重定向:改變默認位置
>:覆蓋重定向,目標文件中的原有內容會被清除;
>>: 追加重定向,新內容會追加至目標文件尾部;
# set -C: 禁止將內容覆蓋輸出至已有文件中(即禁止使用覆蓋重定向已有的文件,只對當前shell生效);
強制覆蓋:>|:cat /etc/fstab >| /etc/a
# set +C: 允許將內容覆蓋輸出至已有文件中
2>: 覆蓋重定向錯誤輸出數據流;
2>>: 追加重定向錯誤輸出數據流;
標準輸出和錯誤輸出各自定向至不同位置:
COMMAND > /path/to/file.out 2> /path/to/error.out:COMMAND執行成功保存在/path/to/file.out文件中;COMMAND執行失敗,保存在/path/to/error.out文件中
標準輸出和錯誤輸出重定向至同一個文件中:
&>:覆蓋重定向
&>>:追加重定向
echo "PATH" &> /tmp/path.out 命令無論執行成功或錯誤,都重定向至/tmp/path.out文件中。
COMMAND > /path/to/file.out 2> &1
COMMAND >> /path/to/file.out 2>> &1
輸入重定向:<
tr命令:轉換或刪除字符
tr [OPTION]... SET1(字符集1) [SET2](或字符集2)
-d :tr -d 'U' 出現U的都刪除
如果只給定一個字符集,就表示在給定的字符裏,凡是在字符集1中出現的字符都移除
如果同時給定字符集1和字符集2,表示給定的字符將第一個字符集中出現字符替換成第二個字符集中的字符(按位替換)
tr abc ABC
輸入:alpa 回車
輸出:AlpA
tr abc ABC < /etc/fstab 在/etc/fstab文件中,所有出現a (b)( c)的字符替換爲對應的A (B)( C)
HERE Documentation:<<
# cat << EOF
# cat > /path/to/somefile << EOF
例如:cat << EOF
> how are you 回車
>how old are you 回車
>EOF 回車
輸出:how are you
how old are you 將以上輸入合成一次輸出
管道:第一個命令的輸出作爲第二個命令的輸入
COMMAND1 | COMMAND2 | COMMAND3 |...
注意:最後一個命令會在當前shell進程的子shell進程中執行;
tee命令:
tee [OPTION]... [FILE]...
練習:
1、將/etc/passwd文件中的前5行內容轉換爲大寫後保存至/tmp/passwd.out文件中;
2、將登錄至將前系統上用戶信息中的後3行的信息轉換爲大寫後保存至/tmp/who.out文件中;
# who | tail -n 3 | tr 'a-z' 'A-Z' > /tmp/who.out
bash的基礎特性(4)
變量類型:
數據存儲格式、存儲空間大小、參與運算種類;
字符型
數值型:
整型
浮點型
強類型:定義變量時必須指定類型、參與運算必須符合類型要求;調用未聲明變量會產生錯誤;
弱類型:無須指定類型,默認均爲字符型;參與運算會自動進行隱式類型轉換;變量無須事先定義可直接調用;如bash
變量賦值:set VAR_NAME=VALUE set可省略(重啓後該變量值會消失)
例NAME=Jerry 聲明變量NAME,並附值爲Jerry。聲明的變量類型默認都爲字符串類型,可用let sum=0直接聲明sum爲整數
引用變量的值:${VARNAME} 。{}有時可以省略。
declare 變量聲明
declare -i SUM=0 聲明sum這個變量爲整數
-x 將變量聲明爲環境變量
bash支持的引號
`` :引用命令執行結果,而不是引用命令執行狀態結果。 例如:userid=`id -u user1` 將id -u user1的執行結果付值變量userid;
"" :弱引用,可以實現內部變量替換。
'':強引用,不完成變量替換。
變量名稱:
1、只能包含字母、數字和下劃線,並且不能數字開頭;
2、不應該跟系統中已有的環境變量重名;
3、最好做到見名知義;
bash變量類型:
環境變量
本地變量(局部變量)
位置變量
特殊變量
1.本地變量:
(set)VARNAME=VALUE: 作用域爲整個bash進程,bash進程結束變量也消失;
2.局部變量:
local VARNAME=VALUE:作用域爲當前代碼段;
3.環境變量:作用域爲當前shell進程及其子進程;
export VARNAME=VALUE
或VARNAME=VALUE
export VARNAME (先設爲本地變量然後再導出)
查看當前shell中的環境變量:printenv或env或export。
腳本在執行時會啓動一個子shell進程;
命令行中啓動的腳本會繼承當前shell環境變量;
系統自動執行的腳本(非命令行啓動)就需要自我定義需要各環境變量;
4.位置變量:引用給定腳本的參數。 例 ./test.sh /etc/passwd /etc/rc.d/rc.sysinit
$1(第一個位置的參數 /etc/passwd), $2(第二個位置的參數 /etc/rc.d/rc.sysinit), …
支持shift 換崗操作:
Shift [n] 剔除幾個位置變量,默認爲1
例:shift
echo $1 (這時輸出的是第二個參數值)
5.特殊變量:bash內置的用來保存某些特殊的變量
$?: 保存上一個命令的執行狀態返回值;
$#:統計腳本參數的個數
$*:參數列表(把所有的參數看成一個字符串)
$@:參數列表(把所有參數的每一個參數當成一個字符串)
$0: 執行腳本時,對指定的路徑取基名即腳本名稱
程序執行後,可能有兩類返回值:
>程序執行結果
>程序狀態返回代碼(0-255)
0: 正確執行
1-255:錯誤執行,1,2,127系統預留;
撤消變量:unset VARNAME
查看當shell中變量:set
在變量中添加多個字符串:ANIMALS=pig:wolf:goat或ANMALS=$ANIMALS:wolf
在shell變量默認都是字符串,所以不能做算術運算。
數組賦值:
Array_Name=("element1" "element2")
也可以對元素進行一個個的賦值。
數組引用:
Array_Name[Index]
示例:判斷給出的文件的行數
#!/bin/bash
linecount="$(wc -l $1| cut -d' ' -f1)" 命令結果有空格的話需要加""。
echo "$1 has $linecount lines."
bash的配置文件:
按生效範圍劃分,存在兩類:
全局配置:
/etc/profile (對所有用戶生效)
/etc/profile.d/*.sh(配置文件過大,會分割成多個片段)
/etc/bashrc
個人配置:(只對某一用戶生效)
~/.bash_profile
~/.bashrc
按功能劃分,存在兩類:
profile類:爲交互式登錄的shell提供配置
全局:/etc/profile, /etc/profile.d/*.sh
個人:~/.bash_profile
功用:
(1) 用於定義環境變量;
(2) 運行命令或腳本;
bashrc類:爲非交互式登錄的shell提供配置
全局:/etc/bashrc
個人:~/.bashrc
功用:
(1) 定義命令別名;
(2) 定義本地變量;
shell登錄:
交互式登錄:讀取配置文件的順序
直接通過終端輸入賬號密碼登錄;
使用“su - UserName”或“su -l UserName”切換的用戶
/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc(相同的變量,後面的會覆蓋前面的值)
非交互式登錄:讀取配置文件的順序
su UserName
圖形界面下打開的終端
執行腳本
~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh
編輯配置文件定義的新配置的生效方式:
(1) 重新啓動shell進程;
(2) 使用source或.命令進程;
問題:
1、定義對所有用戶都生效的別名? /etc/bashrc
2、設置所有用戶登錄系統時輸出提示信息? /etc/profile.d/*.sh
2、讓用戶的PATH環境變量的值多出一個路徑,例如多如/usr/local/apache2/bin
export PATH=$PATH:/usr/local/apache2/bin (不能永久有限)
bash中的算術運算
help let 查看shell支持的算術運算有哪些
+, -, *, /, %, **
實現算術運算:
(1) let var=算術表達式
num1=1 num=3
let sum=$num1+$num2
(2) var=$[算術表達式]
(3) var=$((算術表達式))
(4) var=$(expr arg1 arg2 arg3 ...)
乘法符號有些場景中需要轉義;
bash有內建的隨機數生成器:$RANDOM
增強型賦值:
+=, -=, *=, /=, %=
let varOPERvalue
例如:let count+=1
自增,自減:
let var+=1
let var++
let var-=1
let var--
練習1:寫一個腳本
計算/etc/passwd文件中的第10個用戶和第20用戶的ID之和;
#!/bin/bash
userid1=$(head -n 10 /etc/passwd | tail -n 1 | cut -d: -f3)
userid2=$(head -n 20 /etc/passwd | tail -n 1 | cut -d: -f3)
useridsum=$[$userid1+$userid2]
echo "uid sum: $useridsum"
練習2:寫一個腳本
傳遞兩個文件路徑作爲參數給腳本,計算這兩個文件中所有空白行之和;
#!/bin/bash
spaceline1=$(grep "^[[:space:]]*$" $1 | wc -l)
spaceline2=$(grep "^[[:space:]]*$" $2 | wc -l)
echo "The sum of space line: $[$spaceline1+$spaceline2]"
bash的測試類型:
條件測試的表達式有3種:
1. [ expression ] 一定要有空格才行
例:#let A=3
#let B=6
#[ $A -eq $B ]
#echo $?
輸出1 :所以0表示結果爲真。
2. ` expression ` [[ $A -eq $B ]]
3. test expression test $A -eq $B
數值測試:
-eq: 測試兩個整數是否相等; 比如 [ $A -eq $B ]
-ne: 測試兩個整數是否不等;不等,爲真;相等,爲假;
-gt: 測試一個數是否大於另一個數;大於,爲真;否則,爲假;
-lt: 測試一個數是否小於另一個數;小於,爲真;否則,爲假;
-ge: 大於或等於
-le:小於或等於
字符串測試:
==:是否等於;
>: 是否大於;
<: 是否小於;
!=: 是否不等於;
=~: 左側字符串是否能夠被右側的PATTERN所匹配;
Note: 此表達式一般用於[[ ]]中; [[ "$name" ~= ^O.* ]] 判斷name這個變量的是否以O開頭。
-z "STRING":測試字符串是否爲空,空則爲真,不空則爲假;單目運算符
-n "STRING":測試字符串是否不空,不空則爲真,空則爲假;單目運算符
Note:用於字符串比較時用到的操作數都應該使用引號(單引號或者算引號要看是否需要變量替換);
文件測試
-e FILE:測試文件是否存在
-f FILE: 測試文件是否爲普通文件
-d FILE: 測試指定路徑是否爲目錄
-r FILE: 測試當前用戶對指定文件是否有讀取權限;
-w FILE: 測試當前用戶對指定文件是否有寫權限;
-x FILE: 測試當前用戶對指定文件是否有執行權限;
例:[ -e /etc/inittab ]
[ -x /etc/rc.d/rc.sysinit ]