1拜效、man
manual 是類(lèi) UNIX 系統(tǒng)的標(biāo)準(zhǔn)手冊(cè)工具喷众,共 9 卷,用 man man
可以看到 9 卷分別是什么內(nèi)容:
1 Executable programs or shell commands 可執(zhí)行程序或shell命令
2 System calls (functions provided by the kernel) 系統(tǒng)調(diào)用
3 Library calls (functions within program libraries) 庫(kù)調(diào)用
4 Special files (usually found in /dev) 特殊文件
5 File formats and conventions eg /etc/passwd 文件格式和約定
6 Games 游戲
7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7) 雜項(xiàng)(包括宏和慣例)
8 System administration commands (usually only for root) 系統(tǒng)管理命令(通常僅適用于root用戶)
9 Kernel routines [Non standard] 內(nèi)核例程(非標(biāo)準(zhǔn))
如果只有一個(gè)含義紧憾,直接查詢即可到千,比如man ls
,但有很多是一詞多義的:chmod, chown, chmod, stat, exit, info, socket, flock, open, write, printf, passwd
等等赴穗。
man 1 printf
表示 shell 命令憔四,
man 3 printf
表示 C 語(yǔ)言標(biāo)準(zhǔn)庫(kù)函數(shù),
可以用 -a 選項(xiàng)顯示全部般眉,比如 man -a printf
了赵,按 q
退出之后,可以按回車(chē)鍵表示繼續(xù)看下一卷甸赃,或按 Ctrl-C
直接退出柿汛。
2、#!/bin/bash
#!/bin/bash
放在 shell 腳本開(kāi)頭埠对,是指此腳本使用/bin/bash
來(lái)解釋執(zhí)行络断。
#!/usr/bin/python
也是類(lèi)似的, 表示用/usr/bin/python
來(lái)解釋執(zhí)行 python 腳本项玛,加了這行就可以用./xx.py
的方式來(lái)運(yùn)行了貌笨。
#!/usr/bin/env python
會(huì)去環(huán)境變量路徑中尋找 python 目錄。
3襟沮、shell 運(yùn)行方式
(1) bash 1.sh
創(chuàng)建子進(jìn)程運(yùn)行 1.sh锥惋,需要有 r
權(quán)限。
(2) ./1.sh
創(chuàng)建子進(jìn)程運(yùn)行 1.sh开伏,需要有 r
和 x
權(quán)限膀跌。
(3) source 1.sh
當(dāng)前進(jìn)程運(yùn)行 1.sh,需要有 r
權(quán)限硅则,
(4) . 1.sh
點(diǎn)命令是 source
命令的另一種寫(xiě)法淹父。
如何證明是在當(dāng)前進(jìn)程運(yùn)行株婴,還是創(chuàng)建子進(jìn)程運(yùn)行呢怎虫,下面用 2 種簡(jiǎn)單的方法:
(1) 創(chuàng)建一個(gè)子目錄,然后用 cd
命令
~/test$ mkdir child
~/test$ echo 'cd child;pwd' > 1.sh
使用 bash
執(zhí)行結(jié)束后困介,可以看左邊的提示符大审,當(dāng)前的工作目錄沒(méi)有改變,cd
命令只對(duì)子進(jìn)程產(chǎn)生影響:
~/test$ bash 1.sh
/home/oo/test/child
~/test$
使用 source
執(zhí)行結(jié)束后座哩,當(dāng)前目錄變成了 child 目錄徒扶,因?yàn)?cd
命令對(duì)當(dāng)前進(jìn)程產(chǎn)生了影響:
~/test$ source 1.sh
/home/oo/test/child
~/test/child$
(2) 變量賦值
bash
是創(chuàng)建子進(jìn)程來(lái)執(zhí)行腳本,所以子進(jìn)程的變量根穷,在父進(jìn)不能訪問(wèn)姜骡;
而source
在當(dāng)前進(jìn)程執(zhí)行导坟,所以腳本中對(duì)變量的賦值,當(dāng)前進(jìn)程能訪問(wèn):
$ echo "a=99" > 1.sh
$ bash 1.sh
$ echo $a
$ source 1.sh
$ echo $a
99
4圈澈、內(nèi)部命令惫周,外部命令
通過(guò) type
命令可以查詢某個(gè)命令是內(nèi)部命令、外部命令康栈,還是別名(alias
):
$ type cd
cd is a shell builtin
$ type find
find is /usr/bin/find
$ type ls
ls is aliased to `ls --color=auto'
如果用 bash shell递递,可以通過(guò)help
命令列出所有內(nèi)部命令列表。
區(qū)別:
(1)內(nèi)部命令不創(chuàng)建子進(jìn)程啥么,對(duì)當(dāng)前進(jìn)程有影響登舞,執(zhí)行速度快;
外部命令不在shell中悬荣,保存在一個(gè)獨(dú)立的文件中菠秒,會(huì)創(chuàng)建新的進(jìn)程來(lái)執(zhí)行。
(2)內(nèi)部命令查詢幫助信息用:help 內(nèi)部命令隅熙,比如 help cd
稽煤,
外部命令查詢幫助信息用:外部命令 --help,比如 ls --help
囚戚。
當(dāng)然除了 man
酵熙、help
之外,info
也可以用于查詢幫助信息驰坊。
5匾二、重定向
(1) 輸入重定向 <
$ wc -l < /etc/passwd
32
$ echo 123 > 1.txt
$ read var < 1.txt
$ echo $var
123
(2) 輸出重定向
① > 先清空該文件,再追加內(nèi)容拳芙。
② >> 文件的內(nèi)容不變察藐,在文件末尾追加內(nèi)容。
③ 2> 錯(cuò)誤重定向
$ nothing
nothing: command not found
$ nothing 2> 1.txt
$ cat 1.txt
nothing: command not found
④ &> 表示無(wú)論是正確還是錯(cuò)誤舟扎,都輸出重定向分飞。
(3) 輸入、輸出重定向的組合使用
將開(kāi)始標(biāo)記 和結(jié)束標(biāo)記之間的內(nèi)容作為 cat
的輸入睹限,cat
的輸出重定向到文件 1.txt:
$ cat > 1.txt << EOF
> 123
> 456
> EOF
$ cat 1.txt
123
456
這里的 EOF 只是開(kāi)始和結(jié)尾的 tag譬猫,也可以換成其他的,比如ABCD:
$ cat > 1.txt << ABCD
> 1234
> 5678
> ABCD
$ cat 1.txt
1234
5678
6羡疗、變量
(1) 賦值, =
的兩邊不能有空格染服,否則被解釋為命令:
$ a=123
$ echo $a
123
$ a =123
a: command not found
$ a= 123
123: command not found
(2) 算數(shù)運(yùn)算用 let
,否則默認(rèn)是字符串
$ a=1+2+3
$ echo $a
1+2+3
$ let a=1+2+3
$ echo $a
6
(3) 把命令賦值給變量叨恨,意義不大:
$ a=ls
$ $a -l
(4) 把命令的結(jié)果賦值給變量:
$ a=$(find . -name *.sh)
$ echo $a
(5) 作用范圍
變量只在當(dāng)前 shell 生效柳刮,子shell、父shell 都不能共用。
使用 export
命令之后秉颗,子shell 可以獲取 父shell 的變量痢毒。其他終端不可以。
(6)變量不用了之后蚕甥,可以刪除: unset
變量名闸准。
7、環(huán)境變量
(1)env
命令可以列出所有環(huán)境變量梢灭,一般是大寫(xiě)夷家。
PATH
指定命令搜索路徑,
PS1
可以使當(dāng)前終端顯示更友好敏释,
UID
用戶ID库快,
USER
用戶名。
PWD
當(dāng)前路徑,
LD_LIBRARY_PATH
钥顽、LD_PRELOAD
程序運(yùn)行時(shí)义屏,搜索動(dòng)態(tài)庫(kù)路徑。
(2) set
命令可以列出系統(tǒng)中已經(jīng)存在的 shell 變量蜂大,比 env
命令列出的變量更多闽铐。
$ abcde=1234567
$ set | grep abcde
abcde=1234567
(3) 預(yù)定義變量
$$
:當(dāng)前進(jìn)程的PID號(hào)
$0
:當(dāng)前程序或腳本的名稱(chēng)
$?
:用于返回上一條命令是否成功執(zhí)行。如果成功執(zhí)行奶浦,將返回?cái)?shù)字0兄墅,否則返回非零數(shù)字(通常情況下都返回?cái)?shù)字1)。
$*
或 $@
:保存?zhèn)鬟f給腳本或進(jìn)程的所有參數(shù)
$#
:腳本參數(shù)的個(gè)數(shù)澳叉,(類(lèi)似C語(yǔ)言的 argc)
$1
隙咸、 $2
、 ${10}
等等 :位置變量成洗,從命令行給腳本傳參(類(lèi)似C語(yǔ)言的argv[])五督,還有函數(shù)傳參時(shí)會(huì)使用。
(4) 環(huán)境變量的配置文件
/etc/profile
是所有用戶共用的瓶殃。
~/.bashrc
是某一個(gè)用戶特有的充包。
如果存在重復(fù)定義的變量,/etc/profile
先執(zhí)行遥椿,會(huì)被后執(zhí)行的 ~/.bashrc
覆蓋基矮。萬(wàn)一有變量被重復(fù)定義了,執(zhí)行順序很重要修壕,可以在這 2 個(gè)文件中添加echo
輸出重定向到文件愈捅,來(lái)判斷誰(shuí)先被執(zhí)行遏考。
另外:
su root
是 non-login shell慈鸠,不會(huì)加載所有的配置文件,不建議使用;
su - root
是 login shell青团,會(huì)加載所有配置文件譬巫,推薦使用這種方式。
8督笆、數(shù)組
定義數(shù)組用小括號(hào)芦昔,例如: a=(1 2)
,
訪問(wèn)所有元素 ${a[@]}
娃肿,
數(shù)組元素的個(gè)數(shù) ${#a[@]}
咕缎,
訪問(wèn)單個(gè)元素 ${a[0]}
,負(fù)號(hào)表示倒數(shù)第幾個(gè) ${a[-1]}
料扰。
$ a=( 11 22 33 )
$ echo ${a[@]}
11 22 33
$ echo ${a[*]}
11 22 33
$ echo ${#a[@]}
3
$ echo ${a[0]}
11
$ echo ${a[1]}
22
$ echo ${a[-1]}
33
$ echo ${a[-3]}
11
9凭豪、特殊字符
#
注釋
;
分號(hào)用來(lái)分隔兩條命令。
` 反引號(hào) 與 $() 都是用來(lái)執(zhí)行命令的晒杈。
"
雙引號(hào)(不完全引用)會(huì)對(duì)變量解釋?zhuān)?br>
'
單引號(hào)(完全引用)不解釋變量嫂伞。
$ a=hello
$ echo "$a"
hello
$ echo '$a'
$a
10、整數(shù)運(yùn)算
默認(rèn)會(huì)解釋為字符串拯钻,所以需要用 expr
帖努,注意空格:
$ expr 1 + 2 + 3
6
$ expr 1+ 2 + 3
expr: syntax error
除了 + 還有 - * / % > < 等等,注意轉(zhuǎn)義字符:
$ expr 1 - 2
-1
$ expr 6 \* 6
36
$ expr 30 / 6
5
$ expr 32 % 3
2
$ expr 3 \> 4
0
$ expr 3 \< 4
1
$ expr 3 \<= 3
1
$ expr 3 \!= 3
0
$ expr 3 \!= 4
1
不支持小數(shù)運(yùn)算:
$ expr 5 + 0.5
expr: non-integer argument
另外 length 可以計(jì)算字符串長(zhǎng)度:
$ expr length "hello"
5
**
表示乘方粪般,expr
沒(méi)有乘方功能:
$ let a=2**3
$ echo $a
8
let
簡(jiǎn)寫(xiě)為雙圓括號(hào):
$ ((a=5+6))
$ echo $a
11
11拼余、園括號(hào)()
里面的賦值,不會(huì)影響外面亩歹。
$ a=10;echo $a
10
$ (a=20;echo $a)
20
$ echo $a
10
是圓括號(hào)()創(chuàng)建了一個(gè)子進(jìn)程嗎姿搜,還是其他原因呢?
可以做一個(gè)小實(shí)驗(yàn)捆憎,先打開(kāi) 2 個(gè)終端:
先查看有幾個(gè) bash
進(jìn)程舅柜,可以看到是 5 個(gè):
$ ps aux |grep bash |wc -l
5
$ (a=20;echo $a;sleep 9)
把圓括號(hào)睡眠一下,趁這個(gè)時(shí)間再次查看 bash
數(shù)量躲惰,比剛才多了 1 個(gè)致份,等 sleep
結(jié)束之后再看 bash
數(shù)量又恢復(fù) 5個(gè),說(shuō)明圓括號(hào)()確實(shí)創(chuàng)建了子進(jìn)程:
$ ps aux |grep bash |wc -l
6
另外也可以再通過(guò) cd
命令來(lái)看础拨,圓括號(hào)中改變了工作目錄氮块,并不影響父進(jìn)程:
$ pwd
/home/oo/test
oo@uu:~/test$ (a=20; cd ..; pwd)
/home/oo
oo@uu:~/test$ pwd
/home/oo/test
12、test
命令
test
命令是通過(guò)設(shè)置 $?
的值诡宗, 來(lái)讓我們可以判斷是否正常退出滔蝉,或者條件是否為真,0 為 真塔沃,非 0 為假蝠引。
test
通常有三類(lèi)測(cè)試:字符串、數(shù)字、文件螃概,可以通過(guò) man
查詢具體用法:
man test|grep INTEGER
man test|grep STRING
man test|grep FILE
通過(guò) man test
可以看到 test EXPRESSION
和 [ EXPRESSION ]
兩種寫(xiě)法矫夯,
有時(shí)為了程序美觀,可以把 test
換成方括號(hào)[ ]
的寫(xiě)法吊洼。
(1) 字符串
字符串是否相等训貌,會(huì)區(qū)分大小寫(xiě):
$ [ "abc" = "abc" ]
$ echo $?
0
$ [ "abc" = "a" ]
$ echo $?
1
(2) 整數(shù)
[]
擴(kuò)展為 [[]]
,可以支持更多運(yùn)算符冒窍。
$ test 3 -gt 4
$ echo $?
1
$ [ 3 -gt 4 ]
$ echo $?
1
$ [[ 3 > 4 ]]
$ echo $?
1
(3) 文件
文件是否存在:
$ test -f /etc/passwd
$ echo $?
0
$ test -f /etc/passwd.1234
$ echo $?
1
目錄存在:
$ test -d /etc
$ echo $?
0
文件或目錄存在:
$ test -e /etc
$ echo $?
0
$ test -e /etc/passwd
$ echo $?
0
13递沪、大括號(hào)
(1) 表示某個(gè)范圍內(nèi)的值,主要是給 for
循環(huán)使用的
$ echo {0..3}
0 1 2 3
(2) 減少重復(fù)書(shū)寫(xiě)
cp -v /etc/passwd{,.bak}
相當(dāng)于 cp -v /etc/passwd /etc/passwd.bak
14综液、if
(1)if-then-fi
(2)if-then-else-fi
(3)if-then-elif-then-else-fi
let a=1-6
if [ $a -eq 0 ];
then
echo "a=0"
elif [ $a -lt 0 ];
then
echo "a<0"
else
echo "a>0"
fi
15区拳、case-esac
a=3
case "$a" in
1)
echo "case 1"
;;
2|3)
echo "case 2 or 3"
;;
*)
echo "case *"
;;
esac
case 語(yǔ)句的例子在很多文件都有,比如 grep -n case ~/.bashrc
16意乓、for
for i in {1..3}
do
echo $i
done
for filename in /etc/profile.d/*.sh
do
if [ -x $filename ]; then
source $filename;
echo "source $filename;";
fi
done
下面是 C 語(yǔ)言風(fēng)格的寫(xiě)法:
for ((i=1;i<=3;i++))
do
echo $i
done
17樱调、while
a=1
while [ $a -le 3 ];
do
echo $a;
((a++));
done
用冒號(hào)表示條件為真,寫(xiě)一個(gè)死循環(huán):
while :
do
echo "always"
done
18届良、until
until 循環(huán)與 while 語(yǔ)法一致笆凌,只是條件為假才執(zhí)行循環(huán):
a=8
until [ $a -lt 5 ];
do
echo $a;
((a--));
done
19、break 與 continue
for n in {1..5}
do
if [ $n -eq 3 ];then
break;
fi
echo $n
done
for n in {1..5}
do
if [ $n -eq 3 ];then
continue;
fi
echo $n
done
20士葫、字符串截取命令
basename
命令乞而,可以用來(lái)刪掉后綴名:
$ basename hello.c.diff .diff
hello.c
$ basename hello.c.diff .c.diff
hello
dirname
用于獲取目錄
$ dirname /etc/hosts
/etc
其實(shí)它們不在乎這個(gè)目錄是否真實(shí)存在,只是簡(jiǎn)單的處理一下字符串而已:
$ dirname /1/2/3
/1/2
21慢显、函數(shù)
函數(shù)定義的格式:
函數(shù)名(){ }
$ testfun(){ echo hello;};testfun;
hello
避免函數(shù)內(nèi)部的變量影響到外面爪模,使用 local
關(guān)鍵字限定作用域?yàn)樵摵瘮?shù)。