shell 隨筆

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开伏,需要有 rx 權(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ù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末荚藻,一起剝皮案震驚了整個(gè)濱河市屋灌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌应狱,老刑警劉巖共郭,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異疾呻,居然都是意外死亡除嘹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)岸蜗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)尉咕,“玉大人,你說(shuō)我怎么就攤上這事璃岳∧甓校” “怎么了悔捶?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)晦款。 經(jīng)常有香客問(wèn)我,道長(zhǎng)枚冗,這世上最難降的妖魔是什么缓溅? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮赁温,結(jié)果婚禮上坛怪,老公的妹妹穿的比我還像新娘。我一直安慰自己股囊,他們只是感情好袜匿,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著稚疹,像睡著了一般居灯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上内狗,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天怪嫌,我揣著相機(jī)與錄音,去河邊找鬼柳沙。 笑死岩灭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赂鲤。 我是一名探鬼主播噪径,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼数初!你這毒婦竟也來(lái)了找爱?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤泡孩,失蹤者是張志新(化名)和其女友劉穎缴允,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體珍德,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡练般,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锈候。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片薄料。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖泵琳,靈堂內(nèi)的尸體忽然破棺而出摄职,到底是詐尸還是另有隱情誊役,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布谷市,位于F島的核電站蛔垢,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏迫悠。R本人自食惡果不足惜鹏漆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望创泄。 院中可真熱鬧艺玲,春花似錦、人聲如沸鞠抑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)搁拙。三九已至秒梳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間箕速,已是汗流浹背端幼。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弧满,地道東北人婆跑。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像庭呜,于是被迫代替她去往敵國(guó)和親滑进。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348