日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

一、什么是shell?

shell是一個(gè)用 C 語言編寫的程序,它是用戶使用 linux 的橋梁。Shell 既是一種命令語言,又是一種程序設(shè)計(jì)語言。

Shell 是指一種應(yīng)用程序,這個(gè)應(yīng)用程序提供了一個(gè)界面,用戶通過這個(gè)界面訪問操作系統(tǒng)內(nèi)核的服務(wù)。

Shell屬于內(nèi)置的腳本,程序開發(fā)的效率非常高,依賴于功能強(qiáng)大的命令可以迅速地完成開發(fā)任務(wù)(批處理)語法簡(jiǎn)單,代碼寫起來比較輕松,簡(jiǎn)單易學(xué)。

二、shell的分類

cat /etc/shells

在linux中有很多類型的shell,不同的shell具備不同的功能,shell還決定了腳本中函數(shù)的語法,Linux中默認(rèn)的shell是 /bash/bash(重點(diǎn)),流行的shell有ash、bash、ksh、csh、zsh等,不同的shell都有自己的特點(diǎn)以及用途。

編寫規(guī)范:

#!/bin/bash [指定告知系統(tǒng)當(dāng)前這個(gè)腳本要使用的shell解釋器]

Shell相關(guān)指令

文件命名規(guī)范:

*.sh

.sh是linux下bash shell 的默認(rèn)后綴

Bash 常用快捷鍵

 

快捷鍵

 

作用

 

ctrl+A

 

把光標(biāo)移動(dòng)到命令行開頭。如果我們輸入的命令過長(zhǎng),想要把光標(biāo)移動(dòng)到命令行開頭時(shí)使用。

 

ctrl+E

 

把光標(biāo)移動(dòng)到命令行結(jié)尾。

 

ctrl+C

 

強(qiáng)制終止當(dāng)前的命令。

 

ctrl+L

 

清屏,相當(dāng)于clear命令。

 

ctrl+U

 

刪除或剪切光標(biāo)之前的命令。我輸入了一行很長(zhǎng)的命令,不用使用退格鍵一個(gè)一個(gè)字符的刪除,使用這個(gè)快捷鍵會(huì)更加方便

 

ctrl+K

 

刪除或剪切光標(biāo)之后的內(nèi)容。

 

ctrl+Y

 

粘貼ctrl+U或ctul+K剪切的內(nèi)容。

 

ctrl+R

 

在歷史命令中搜索,按下ctrl+R之后,就會(huì)出現(xiàn)搜索界面,只要輸入搜索內(nèi)容,就會(huì)從歷史命令中搜索。

 

ctrl+D

 

退出當(dāng)前終端。

 

ctrl+Z

 

暫停,并放入后臺(tái)。這個(gè)快捷鍵牽扯工作管理的內(nèi)容,我們?cè)谙到y(tǒng)管理章節(jié)詳細(xì)介紹。

 

ctrl+S

 

暫停屏幕輸出。

 

ctrl+Q

 

恢復(fù)屏幕輸出。

輸入輸出重定向

linux 的標(biāo)準(zhǔn)輸入與輸出

 

設(shè)備

 

設(shè)備名

 

文件描述符

 

類型

 

鍵盤

 

/dev/stdin

 

0

 

標(biāo)準(zhǔn)輸入

 

顯示器

 

/dev/stdout

 

1

 

標(biāo)準(zhǔn)輸出

 

顯示器

 

/dev/stderr

 

2

 

標(biāo)準(zhǔn)錯(cuò)誤輸出

輸入重定向

輸入重定向:是指不使用系統(tǒng)提供的標(biāo)準(zhǔn)輸入端口,而進(jìn)行重新的指定。換言之,輸入重定向就是不使用標(biāo)準(zhǔn)輸入端口輸入文件,而是使用指定的文件作為標(biāo)準(zhǔn)輸入設(shè)備。(重定向簡(jiǎn)單理解就是使用 “<”符來修改標(biāo)準(zhǔn)輸入設(shè)備)

 

類型

 

符號(hào)(語法)

 

功能

 

標(biāo)準(zhǔn)輸入

 

命令<文件1

 

命令把文件1的內(nèi)容作為標(biāo)準(zhǔn)輸入設(shè)備

 

標(biāo)識(shí)符限定輸入

 

命令<<標(biāo)識(shí)符

 

命令把標(biāo)準(zhǔn)輸入中讀入內(nèi)容,直到遇到“標(biāo)識(shí)符”分解符為止

 

輸入輸出重定向(同時(shí)使用)

 

命令< 文件1 >文件2

 

命令把文件1的內(nèi)容作為標(biāo)準(zhǔn)輸入,把文件2作為標(biāo)準(zhǔn)輸出。

輸出重定向

輸出重定向:(通俗的講,重定向輸出就是把要輸出的文件信息寫入到一個(gè)文件中去,而不是將要輸出的文件信息輸出到控制臺(tái)(顯示屏),在linux中,默認(rèn)的標(biāo)準(zhǔn)輸出設(shè)備是控制臺(tái)(或稱為顯示器),用戶輸出的信息默認(rèn)情況下都會(huì)顯示到控制臺(tái).

&表示全部文件,文件不管對(duì)錯(cuò),1表示標(biāo)準(zhǔn)輸出文件,2表示標(biāo)準(zhǔn)錯(cuò)誤輸出。

 

類型

 

符號(hào)(語法)

 

功能

 

標(biāo)住輸出重定向

 

命令 > 文件

 

以覆蓋方式,把命令的正確輸出內(nèi)容輸出到指定的文件或設(shè)備當(dāng)中

 

標(biāo)住輸出重定向

 

命令 >> 文件

 

以追加方式,把命令的正確輸出內(nèi)容輸出到指定的文件或設(shè)備當(dāng)中

 

標(biāo)準(zhǔn)錯(cuò)誤輸出重定向

 

錯(cuò)誤命令 2> 文件

 

以覆蓋方式,把命令的錯(cuò)誤輸出輸出到指定的文件或設(shè)備當(dāng)中

 

標(biāo)準(zhǔn)錯(cuò)誤輸出重定向

 

錯(cuò)誤命令 2>> 文件

 

以追加方式,把命令的錯(cuò)誤輸出輸出到指定的文件或設(shè)備當(dāng)中

 

正確輸出和錯(cuò)誤輸出同時(shí)保存

 

命令 > 文件 2>&1

 

以覆蓋的方式,把正確輸出和錯(cuò)誤輸出都保存到同一個(gè)文件當(dāng)中。

 

正確輸出和錯(cuò)誤輸出同時(shí)保存

 

命令 >> 文件 2>&1

 

以追加的方式,把正確輸出和錯(cuò)誤輸出都保存到同一個(gè)文件當(dāng)中。

 

正確輸出和錯(cuò)誤輸出同時(shí)保存

 

命令 &> 文件

 

以覆蓋的方式,把正確輸出和錯(cuò)誤輸出都保存到同一個(gè)文件當(dāng)中。

 

正確輸出和錯(cuò)誤輸出同時(shí)保存

 

命令 &>> 文件

 

以追加的方式,把正確輸出和錯(cuò)誤輸出都保存到同一個(gè)文件當(dāng)中。

 

正確輸出和錯(cuò)誤輸出同時(shí)保存

 

命令 >> 文件1 2>>文件2

 

把正確的輸出追加到文件1中,把錯(cuò)誤的輸出追加到文件2中。

/dev/null 文件

如果希望執(zhí)行某個(gè)命令,但又不希望在屏幕上顯示輸出結(jié)果,那么可以將輸出重定向到 /dev/null中.

[root@localhost ~]$ command > dev/null

多命令順序執(zhí)行

 

多命令執(zhí)行符

 

作用

 

格式

 

 

命令1 ;命令2

 

多個(gè)命令順序執(zhí)行,命令之間沒有任何邏輯聯(lián)系

 

&&

 

命令1 && 命令2

 

當(dāng)命令1正確執(zhí)行(? = 0 ) , 則命令2才會(huì)執(zhí)行;當(dāng)命令 1執(zhí)行不正確(?=0),則命令2不會(huì)執(zhí)行

 

||

 

命令1 || 命令2

 

當(dāng)命令1執(zhí)行不正確(?≠0),則命令2才會(huì)執(zhí)行;當(dāng)命令1正確執(zhí)行(?≠0),則命令2不會(huì)執(zhí)行.

shell腳本的執(zhí)行

[root@localhost ~]$ vim test.sh

#!/bin/bash

echo “hello world”

兩種方式執(zhí)行shell腳本

第一種:給文件增加執(zhí)行權(quán)限

[root@localhost ~]$ chmod u+x test.sh

[root@localhost ~]$ ./test.sh #絕對(duì)路徑或相對(duì)路徑執(zhí)行

第二種(了解):通過Bash調(diào)用執(zhí)行腳本

[root@localhost ~]$ bash test.sh

三、shell變量

什么是變量?

在一個(gè)腳本周期內(nèi),其值可以發(fā)生改變的量就是變量。

1. 變量的命名規(guī)則:

在定義變量時(shí),有一些規(guī)則需要遵守:

l 命名只能使用英文字母,數(shù)字和下劃線,首個(gè)字符不能以數(shù)字開頭。

l 等號(hào)左右兩側(cè)不能有空格,可以使用下劃線“_”,變量的值如果有空格,需要使用單引號(hào)或雙引號(hào)包括。如:“test=“hello world!””。其中雙引號(hào)括起來的內(nèi)容“$”,“(”和反引號(hào)都擁有特殊含義,而單引號(hào)括起來的內(nèi)容都是普通字符。

l 不能使用標(biāo)點(diǎn)符號(hào),不能使用bash里的關(guān)鍵字(可用help命令查看保留關(guān)鍵字)。

l 環(huán)境變量建議大寫,便于區(qū)分

l 如果需要增加變量的值,那么可以進(jìn)行變量值的疊加。不過變量需要用雙引號(hào)包含"$變量名"或用${變量名}包含變量名。

<!---->

[root@localhost ~]$ test=123

[root@localhost ~]$ test="$test"456

[root@localhost ~]$ echo $test

123456

#疊加變量test,變量值變成了123456

[root@localhost ~]$ test=${test}789

[root@localhost ~]$ echo $test

123456789

#再疊加變量test,變量值編程了123456789

關(guān)于單雙引號(hào)的問題:

雙引號(hào)能夠識(shí)別變量,雙引號(hào)能夠?qū)崿F(xiàn)轉(zhuǎn)義(類似于“*”)

單引號(hào)是不能識(shí)別變量,只會(huì)原樣輸出,單引號(hào)是不能轉(zhuǎn)義的

shell中特殊符號(hào)

 

符號(hào)

 

作用

 

''

 

單引號(hào)。在單引號(hào)中所有的特殊符號(hào),如“$”和”(反引號(hào))都沒有特殊含義。單引號(hào)括起來的都是普通字符,會(huì)原樣輸出

 

""

 

雙引號(hào)。在雙引號(hào)中特殊符號(hào)都沒有特殊含義.“$”表示“調(diào)用變量的值”,“`”(esc鍵下面)表示“引用命令”,“”表示“轉(zhuǎn)義符”。

 

``

 

反引號(hào)。反引號(hào)括起來的內(nèi)容是系統(tǒng)命令,在Bash中會(huì)先執(zhí)行它。和()作用一 樣, 不過推薦使用(),因?yàn)榉匆?hào)非常容易看錯(cuò)。

 

$()

 

和反引號(hào)作用一樣,用來引用系統(tǒng)命令。(推薦使用)

 

()

 

用于一串命令執(zhí)行時(shí),()中的命令會(huì)在子Shell中運(yùn)行

 

{}

 

用于一串命令執(zhí)行時(shí),{ }中的命令會(huì)在當(dāng)前Shell中執(zhí)行。也可以用于變量變形與替換。

 

[ ]

 

用于變量的測(cè)試。

 

#

 

在Shell腳本中,#開頭的行代表注釋。

 

$

 

用于調(diào)用變量的值,如需要調(diào)用變量name的值時(shí),需要用$name的方式得到變量的值。

 

 

轉(zhuǎn)義符,跟在之后的特殊符號(hào)將失去特殊含義,變?yōu)槠胀ㄗ址H?將輸出“$”符號(hào),而不當(dāng)做是變量引用。

單引號(hào)和雙引號(hào)

[root@localhost ~]$ name=sc

#定義變量name 的值是sc

[root@localhost ~]$ echo '$name'

$name

#如果輸出時(shí)使用單引號(hào),則$name被認(rèn)為是字符串

[root@localhost ~]$ echo "$name"

sc

#如果輸出時(shí)使用雙引號(hào),則會(huì)輸出變量name的值 sc

 

[root@localhost ~]$ echo `date`

2018年10月21日星期一18:16:33 CST

#反引號(hào)括起來的命令會(huì)正常執(zhí)行

[root@localhost ~]$ echo '`date`'

`date`

#但是如果反引號(hào)命令被單引號(hào)括起來,那么這個(gè)命令不會(huì)執(zhí)行,―date`會(huì)被當(dāng)成普通字符輸出

[root@localhost ~]$ echo "`date'"

2018年10月21日星期一18:14:21 CST

#如果是雙引號(hào)括起來,那么這個(gè)命令又會(huì)正常執(zhí)行

反引號(hào)

[root@localhost ~]$ echo ls

ls

#如果命令不用反引號(hào)包含,命令不會(huì)執(zhí)行,而是直接輸出

[root@localhost ~]$ echo `ls`

anaconda-ks.cfginstall.loginstall.log.syslog sh test testfile

#只有用反引號(hào)包括命令,這個(gè)命令才會(huì)執(zhí)行

[root@localhost ~]$ echo $(date)

2018年10月21日星期一18:25:09 CST

#使用$(命令)的方式也是可以的

2. 變量的分類

l 用戶自定義變量: 這種變量是最常見的變量,由用戶自由定義變量名和變量的值。

l 環(huán)境變量: 這種變量中主要保存的是和系統(tǒng)操作環(huán)境相關(guān)的數(shù)據(jù),比如當(dāng)前登錄用戶,用戶的家目錄,命令的提示符等。不是太好理解吧,那么大家還記得在windows中,同一臺(tái)電腦可以有多個(gè)用戶登錄,而且每個(gè)用戶都可以定義自己的桌面樣式和分辨率,這些其實(shí)就是Windows的操作環(huán)境,可以當(dāng)做是Windows的環(huán)境變量來理解。環(huán)境變量的變量名可以自由定義,但是一般對(duì)系統(tǒng)起作用的環(huán)境變量的變量名是系統(tǒng)預(yù)先設(shè)定好的。

l 位置參數(shù)變量: 這種變量主要是用來向腳本當(dāng)中傳遞參數(shù)或數(shù)據(jù)的,變量名不能自定義,變量作用是固定的。

l 預(yù)定義變量: 是Bash中已經(jīng)定義好的變量,變量名不能自定義,變量作用也是固定的。

 

變量分類

 

名稱

 

作用

 

內(nèi)容

 

用戶自定義變量

 

自定義

 

自定義

 

自定義

 

用戶自定義環(huán)境變量

 

自定義

 

自定義

 

自定義

 

系統(tǒng)自帶環(huán)境變量(/etc/profile)

 

確定

 

確定

 

自定義

 

位置參數(shù)變量

 

確定

 

自定義

 

自定義

 

預(yù)定義變量

 

確定

 

自定義

 

自定義

2.1 用戶自定義變量

2.1.1 變量定義

[root@localhost ~]$ 2name="shen chao"

-bash: 2name=shen chao: command not found

#變量名不能用數(shù)字開頭

[root@localhost ~]$ name = "shenchao"

-bash: name: command not found

#等號(hào)左右兩側(cè)不能有空格

[root@localhost ~]$ name=shen chao

-bash: chao: command not found

#變量的值如果有空格,必須用引號(hào)包含

2.1.2 變量調(diào)用

[root@localhost ~]$ name="shen chao"

#定義變量name

[root@localhost ~]$ echo $name #調(diào)用變量使用 $變量名

shen chao

#輸出變量name的值

2.1.3 變量查看

[root@localhost ~]$ set [選項(xiàng)]

選項(xiàng):

-u:如果設(shè)定此選項(xiàng),調(diào)用未聲明變量時(shí)會(huì)報(bào)錯(cuò)(默認(rèn)無任何提示)

-x:如果設(shè)定此選項(xiàng),在命令執(zhí)行之前,會(huì)把命令先輸出一次

+<參數(shù)> :取消某個(gè)set曾啟動(dòng)的參數(shù)。

 

[root@localhost ~]$ set

BASH=/bin/bash

…省略部分輸出…

name='shen chao'

#直接使用set 命令,會(huì)查詢系統(tǒng)中所有的變量,包含用戶自定義變量和環(huán)境變量

[root@localhost ~]$ set -u

[root@localhost ~]$ echo $file

-bash: file: unbound variable

#當(dāng)設(shè)置了-u選項(xiàng)后,如果調(diào)用沒有設(shè)定的變量會(huì)有報(bào)錯(cuò)。默認(rèn)是沒有任何輸出的。

[root@localhost ~]$ set -x

[root@localhost ~]$ ls

+ls --color=auto

anaconda-ks.cfginstall.loginstall.log.syslog sh tdir testtestfile

#如果設(shè)定了-x選項(xiàng),會(huì)在每個(gè)命令執(zhí)行之前,先把命令輸出一次

 

[root@localhost ~]$ set +x

#取消啟動(dòng)的x參數(shù)

2.1.4 變量刪除

[root@localhost ~]$ unset 變量名

2.2 環(huán)境變量

2.2.1 環(huán)境變量設(shè)置

[root@localhost ~]$ export age="18"

#使用export聲明的變量即是環(huán)境變量

2.2.2 環(huán)境變量查詢和刪除

env命令和set命令的區(qū)別

set命令可以查看所有變量,而env命令只能查看環(huán)境變量。

[root@localhost ~]$ unset gender #刪除環(huán)境變量gender

[root@localhost ~]$ env | grep gender

2.2.3 系統(tǒng)默認(rèn)環(huán)境變量

[root@localhost ~]$ env

HOSTNAME=localhost.localdomain #主機(jī)名

SHELL=/bin/bash #當(dāng)前的shell

TERM=linux #終端環(huán)境

HISTSIZE=1000 #歷史命令條數(shù)

SSH_CLIENT=192.168.4.15 22 #當(dāng)前操作環(huán)境是用ssh連接的,這里記錄客戶端ip

SSH_TTY=/dev/pts/1 #ssh連接的終端時(shí)pts/1

USER=root #當(dāng)前登錄的用戶

..........更多參數(shù)可以使用set和env命令查看.............

2.3 位置參數(shù)變量

 

位置參數(shù)變量

 

作用

 

$n

 

n為數(shù)字,$0表示當(dāng)前 Shell腳本程序的名稱,$1-9代表 第一到第九個(gè)參數(shù) , 十以上的參數(shù)需要用大括號(hào)包含,如9代表第一到第九個(gè)參數(shù),十以上的參數(shù)需要用大括號(hào)包含,如9代表第一到第九個(gè)參數(shù),十以上的參數(shù)需要用大括號(hào)包含,如${10}

 

$*

 

這個(gè)變量代表命令行中所有的參數(shù),$把所有的參數(shù)看成一個(gè)整體

 

$@

 

這個(gè)變量也代表命令行中所有的參數(shù),不過$@把每個(gè)參數(shù)區(qū)分對(duì)待

 

$#

 

這個(gè)變量代表命令行中所有參數(shù)的個(gè)數(shù)

$1 是你給你寫的shell腳本傳的第一個(gè)參數(shù),$2 是你給你寫的shell腳本傳的第二個(gè)參數(shù)…

[root@localhost sh]$ vim test.sh

#!/bin/sh

echo "shell腳本本身的名字: $0"

echo "傳給shell的第一個(gè)參數(shù): $1"

echo "傳給shell的第二個(gè)參數(shù): $2"

保存退出后,你在Test.sh所在的目錄下輸入 bash Test.sh 1 2

結(jié)果輸出:

shell腳本本身的名字: Test.sh

傳給shell的第一個(gè)參數(shù): 1

傳給shell的第二個(gè)參數(shù): 2

$*會(huì)把接收的所有參數(shù)當(dāng)成一個(gè)整體對(duì)待,而$@則會(huì)區(qū)分對(duì)待接收到的所有參數(shù)。舉個(gè)例子:

[root@localhost sh]$ vi parameter2.sh

#!/bin/bash

for i in"$*"

#定義for循環(huán),in后面有幾個(gè)值,for會(huì)循環(huán)多少次,注意“$*”要用雙引號(hào)括起來

#每次循環(huán)會(huì)把in后面的值賦予變量i

#Shell把$*中的所有參數(shù)看成是一個(gè)整體,所以這個(gè)for循環(huán)只會(huì)循環(huán)一次

do

echo "The parameters is: $i"

#打印變量$i的值

done

x=1

#定義變量x的值為1

for y in"$@"

#同樣in后面的有幾個(gè)值,for循環(huán)幾次,每次都把值賦予變量y

#可是Shel1中把“$@”中的每個(gè)參數(shù)都看成是獨(dú)立的,所以“$@”中有幾個(gè)參數(shù),就會(huì)循環(huán)幾次

do

echo "The parameter$x is: $y"

#輸出變量y的值

x=$(( $x +1 ))

#然變量x每次循環(huán)都加1,為了輸出時(shí)看的更清楚

done

2.4 預(yù)定義變量

 

預(yù)定義變量

 

作用

 

$?

 

最后一次執(zhí)行的命令的返回狀態(tài)。如果這個(gè)變量的值為0,證明上一個(gè)命令正確執(zhí)行;如果這個(gè)變量的值為非О(具體是哪個(gè)數(shù),由命令自己來決定),則證明上一個(gè)命令執(zhí)行不正確了。

 

$$

 

當(dāng)前進(jìn)程的進(jìn)程號(hào)(PID)

 

$!

 

后臺(tái)運(yùn)行的最后一個(gè)進(jìn)程的進(jìn)程號(hào)(PID)

先來看看”$?”這個(gè)變量,舉個(gè)例子說明

[root@localhost sh]$ ls

count.sh hello.sh parameter2.sh parameter.sh

#ls命令正確執(zhí)行

[root@localhost sh]$ echo $?

#預(yù)定義變量“$?”的值是0,證明上一個(gè)命令執(zhí)行正確

[root@localhost sh]$ ls install.log

ls:無法訪問install.log:沒有那個(gè)文件或目錄

#當(dāng)前目錄中沒有install.log文件,所以ls命令報(bào)錯(cuò)了

[root@localhost sh]$ echo $?

2

#變量“$?”返回一個(gè)非0的值,證明上一個(gè)命令沒有正確執(zhí)行

#至于錯(cuò)誤的返回值到底是多少,是在編寫ls命令時(shí)定義好的,如果碰到文件不存在就返回?cái)?shù)值2

再來說明下”$$”和”$!”這兩個(gè)預(yù)定義變量

[root@localhost sh]$ vi variable.sh

#!/bin/bash

echo "The current process is $$"

#輸出當(dāng)前進(jìn)程的PID.

#這個(gè)PID就是variable.sh這個(gè)腳本執(zhí)行時(shí),生成的進(jìn)程的PID

find /root -name hello.sh &

#使用find命令在root目錄下查找hello.sh文件

#符號(hào)&的意思是把命令放入后臺(tái)執(zhí)行,工作管理我們?cè)谙到y(tǒng)管理章節(jié)會(huì)詳細(xì)介紹

echo "The last one Daemon process is $!"

#輸出這個(gè)后臺(tái)執(zhí)行命令的進(jìn)程的PID,也就是輸出find命令的PID號(hào)

3. 只讀變量

[root@localhost sh]$ vi readonly.sh

#!/bin/bash

a=10

#語法:readonly 變量名

readonly a

a=20 #會(huì)報(bào)錯(cuò)readonly variable

echo $a

4. 接受鍵盤輸入

[root@localhost ~]$ read [選項(xiàng)][變量名]

選項(xiàng):

-a 后跟一個(gè)變量,該變量會(huì)被認(rèn)為是個(gè)數(shù)組,然后給其賦值,默認(rèn)是以空格為分割符。

-p: “提示信息”:在等待read輸入時(shí),輸出提示信息

-t: 秒數(shù):read命令會(huì)一直等待用戶輸入,使用此選項(xiàng)可以指定等待時(shí)間

-n: 數(shù)字:read命令只接受指定的字符數(shù),就會(huì)執(zhí)行

-s: 隱藏輸入的數(shù)據(jù),適用于機(jī)密信息的輸入

-d: 后面跟一個(gè)標(biāo)志符,其實(shí)只有其后的第一個(gè)字符有用,作為結(jié)束的標(biāo)志。

-e: 在輸入的時(shí)候可以使用命令補(bǔ)全功能。

變量名:

變量名可以自定義,如果不指定變量名,會(huì)把輸入保存入默認(rèn)變量REPLY.

如果只提供了一個(gè)變量名,則整個(gè)輸入行賦予該變量.

如果提供了一個(gè)以上的變量名,則輸入行分為若干字,一個(gè)接一個(gè)地賦予各個(gè)變量,而命令行上的最后一個(gè)變量取得剩余的所有字

寫個(gè)例子來解釋下read命令:

[root@localhost sh]$ vi read.sh

#!/bin/bash

 

read -t 30 -p "Please input your name: " name

#提示“請(qǐng)輸入姓名”并等待30 秒,把用戶的輸入保存入變量name 中

echo "Name is $name"

#看看變量“$name”中是否保存了你的輸入

 

read -s -t 30 -p "Please enter your age: " age

#提示“請(qǐng)輸入年齡”并等待30秒,把用戶的輸入保存入變量age中

#年齡是隱私,所以我們用“-s”選項(xiàng)隱藏輸入

echo -e "n"

#調(diào)整輸出格式,如果不輸出換行,一會(huì)的年齡輸出不會(huì)換行

echo "Age is $age"

 

read -n 1 -t 30 -p "Please select your gender[M/F]:" gender

#提示“請(qǐng)選擇性別”并等待30秒,把用戶的輸入保存入變量gender

#使用“-n1”選項(xiàng)只接收一個(gè)輸入字符就會(huì)執(zhí)行(都不用輸入回車)

echo -e "n"

echo "Sex is $gender"

四、shell 運(yùn)算符

在shell中,運(yùn)算符和其他編程腳本語言一樣,常見的有算數(shù)運(yùn)算符、關(guān)系運(yùn)算符、邏輯運(yùn)算符、字符串運(yùn)算符、文件測(cè)試運(yùn)算符等

1. 算數(shù)運(yùn)算符

原生bash不支持簡(jiǎn)單的數(shù)學(xué)運(yùn)算,但是可以通過其他命令來實(shí)現(xiàn),例如 awk 和 expr,expr 最常用。

expr 是一款表達(dá)式計(jì)算工具,使用它能完成表達(dá)式的求值操作。

例如,兩個(gè)數(shù)相加(注意使用的是反引號(hào) ` 而不是單引號(hào) '):

[root@localhost ~]$ vi computer.sh

#!/bin/bash

val=`expr 2 + 2`

echo "兩數(shù)之和為 : $val"

#注意

#表達(dá)式和運(yùn)算符之間要有空格,例如 2+2 是不對(duì)的,必須寫成 2 + 2,這與我們熟悉的大多數(shù)編程語言不一樣。

#完整的表達(dá)式要被 ` ` 包含,注意這個(gè)字符不是常用的單引號(hào),在 Esc 鍵下邊。

下表列出了常用的算術(shù)運(yùn)算符,假定變量 a 為 10,變量 b 為 20

 

運(yùn)算符

 

說明

 

舉例

 

+

 

加法

 

expr $a + $b 結(jié)果為 30。

 

-

 

減法

 

expr $a - $b 結(jié)果為 -10。

 

*

 

乘法

 

expr $a * $b 結(jié)果為 200。

 

/

 

除法

 

expr $b / $a 結(jié)果為 2。

 

%

 

取余

 

expr $b % $a 結(jié)果為 0。

 

=

 

賦值

 

a=$b 將把變量 b 的值賦給 a。

 

==

 

相等。用于比較兩個(gè)數(shù)字,相同則返回 true(真)。

 

[ $a == $b ] 返回 false(假)。

 

!=

 

不相等。用于比較兩個(gè)數(shù)字,不相同則返回 true。

 

[ $a != $b ] 返回 true。

注意:條件表達(dá)式要放在方括號(hào)之間,并且要有空格,必須寫成 [ $a == $b ]。

[root@localhost ~]$ vi computers.sh

#!/bin/bash

a=10

b=20

echo ' '

echo 'a+b= ' `expr $a + $b`

echo 'a-b= ' `expr $a - $b`

echo 'a*b= ' `expr $a * $b`

echo 'a/b= ' `expr $a / $b`

echo 'a%b= ' `expr $a % $b`

 

#判斷是否相等

if [ $a == $b ]

then

echo 'a等于b'

else

echo 'a不等于b'

fi

2. 關(guān)系運(yùn)算符

關(guān)系運(yùn)算符只支持?jǐn)?shù)字,不支持字符串,除非字符串的值是數(shù)字。

下表列出了常用的關(guān)系運(yùn)算符,假定變量 a 為 10,變量 b 為 20:

 

運(yùn)算符

 

單詞

 

說明

 

舉例

 

-eq

 

equal

 

檢測(cè)兩個(gè)數(shù)是否相等,相等返回 true。

 

[ $a -eq $b ] 返回 false。

 

-ne

 

not equal

 

檢測(cè)兩個(gè)數(shù)是否相等,不相等返回 true。

 

[ $a -ne $b ] 返回 true。

 

-gt

 

great than

 

檢測(cè)左邊的數(shù)是否大于右邊的,如果是,則返回 true。

 

[ $a -gt $b ] 返回 false。

 

-lt

 

less than

 

檢測(cè)左邊的數(shù)是否小于右邊的,如果是,則返回 true。

 

[ $a -lt $b ] 返回 true。

 

-ge

 

great than or equal

 

檢測(cè)左邊的數(shù)是否大于等于右邊的,如果是,則返回 true。

 

[ $a -ge $b ] 返回 false。

 

-le

 

less than or equal

 

檢測(cè)左邊的數(shù)是否小于等于右邊的,如果是,則返回 true。

 

[ $a -le $b ] 返回 true。

[root@localhost ~]$ [ 10 -gt 10 ]

[root@localhost ~]$ echo $?

1

[root@localhost ~]$ [ 10 -eq 10 ]

[root@localhost ~]$ echo $?

0

案例:判斷當(dāng)前輸入的用戶是否存在。如果存在則提示“用戶存在”否則提示“用戶不存在”。

如果要在shell腳本使用linux命令,可以使用$()包裹命令

例如:disk_size=$(df -h | awk ‘NR==2 {print $5}’)

[root@localhost ~]$ vim demo.sh

#!/bin/bash

#接受用戶的輸入

read -p '請(qǐng)輸入需要查詢的用戶名:' username

 

#獲取指定用戶名在passwd文件中出現(xiàn)的次數(shù)

count=$(cat /etc/passwd | grep $username | wc -l)

#count=`cat /etc/passwd | grep $username | wc -l`

 

#判斷出現(xiàn)的次數(shù),如果次數(shù)=0則用戶不存在,反之存在

if [ $count == 0 ]

then

echo '用戶不存在'

else

echo '用戶存在'

fi

3. 邏輯運(yùn)算符

下表列出了常用的布爾運(yùn)算符,假定變量 a 為 10,變量 b 為 20:

 

運(yùn)算符

 

說明

 

舉例

 

!

 

非運(yùn)算,表達(dá)式為 true 則返回 false,否則返回 true。

 

[ ! false ] 返回 true。

 

-o

 

或(或者)運(yùn)算,有一個(gè)表達(dá)式為 true 則返回 true。

 

[ $a -lt 20 -o $b -gt 100 ] 返回 true。

 

-a

 

與(并且)運(yùn)算,兩個(gè)表達(dá)式都為 true 才返回 true。

 

[ $a -lt 20 -a $b -gt 100 ] 返回 false。

或運(yùn)算:一個(gè)為真即為真,全部為假才是假

與運(yùn)算:一個(gè)為假即為假,全部為真才是真

4. 字符串運(yùn)算符

下表列出了常用的字符串運(yùn)算符,假定變量 a 為 “abc”,變量 b 為 “efg”:

 

運(yùn)算符

 

說明

 

舉例

 

=

 

檢測(cè)兩個(gè)字符串是否相等,相等返回 true。

 

[ $a = $b ] 返回 false。

 

!=

 

檢測(cè)兩個(gè)字符串是否相等,不相等返回 true。

 

[ $a != $b ] 返回 true。

 

-z

 

檢測(cè)字符串長(zhǎng)度是否為0,為0返回 true。

 

[ -z $a ] 返回 false。

 

-n

 

檢測(cè)字符串長(zhǎng)度是否為0,不為0返回 true。

 

[ -n $a ] 返回 true。

 

str

 

檢測(cè)字符串是否為空,不為空返回 true。

 

[ $a ] 返回 true。

5. 文件測(cè)試運(yùn)算符(重點(diǎn))

文件測(cè)試運(yùn)算符用于檢測(cè) Unix/Linux 文件的各種屬性。

 

操作符

 

說明

 

舉例

 

-b file

 

檢測(cè)文件是否是塊設(shè)備文件,如果是,則返回 true。

 

[ -b $file ] 返回 false。

 

-c file

 

檢測(cè)文件是否是字符設(shè)備文件,如果是,則返回 true。

 

[ -c $file ] 返回 false。

 

-d file

 

檢測(cè)文件是否是目錄,如果是,則返回 true。

 

[ -d $file ] 返回 false。

 

-f file

 

檢測(cè)文件是否是普通文件(既不是目錄,也不是設(shè)備文件),如果是,則返回 true。

 

[ -f $file ] 返回 true。

 

-g file

 

檢測(cè)文件是否設(shè)置了 SGID 位,如果是,則返回 true。

 

[ -g $file ] 返回 false。

 

-k file

 

檢測(cè)文件是否設(shè)置了粘著位(Sticky Bit),如果是,則返回 true。

 

[ -k $file ] 返回 false。

 

-p file

 

檢測(cè)文件是否是有名管道,如果是,則返回 true。

 

[ -p $file ] 返回 false。

 

-u file

 

檢測(cè)文件是否設(shè)置了 SUID 位,如果是,則返回 true。

 

[ -u $file ] 返回 false。

 

-r file

 

檢測(cè)文件是否可讀,如果是,則返回 true。

 

[ -r $file ] 返回 true。

 

-w file

 

檢測(cè)文件是否可寫,如果是,則返回 true。

 

[ -w $file ] 返回 true。

 

-x file

 

檢測(cè)文件是否可執(zhí)行,如果是,則返回 true。

 

[ -x $file ] 返回 true。

 

-s file

 

檢測(cè)文件是否為空(文件大小是否大于0),不為空返回 true。

 

[ -s $file ] 返回 true。

 

-e file

 

檢測(cè)文件(包括目錄)是否存在,如果是,則返回 true。

 

[ -e $file ] 返回 true。

注意:權(quán)限幾個(gè)判斷,如果只有一個(gè)部分符合,則認(rèn)為是有權(quán)限的。

五、流程控制

1. if條件判斷

1.1 單分支if條件

語法:

if [ 條件判斷式 ]

then

程序

fi

案例:統(tǒng)計(jì)根分區(qū)使用率

[root@localhost ~]$ vi sh/if1.sh

#!/bin/bash

#統(tǒng)計(jì)根分區(qū)使用率

rate=$(df -h | grep "/dev/sda2" | awk '{print $5}’| cut -d "%"-f1)

#把根分區(qū)使用率作為變量值賦予變量rate

if [ $rate -ge 80 ]

#判斷rate的值如果大于等于80,則執(zhí)行then程序

then

echo "Warning!/dev/sda3 is fu11!!"

#打印警告信息。在實(shí)際工作中,也可以向管理員發(fā)送郵件。

fi

案例:創(chuàng)建目錄

[root@localhost ~]$ vi sh/add_dir.sh

#!/bin/bash

#創(chuàng)建目錄,判斷是否存在,存在就結(jié)束,反之創(chuàng)建

echo "當(dāng)前腳本名稱為$0"

DIR="/media/cdrom"

if [ ! -e $DIR ]

then

mkdir -p $DIR

fi

echo "$DIR 創(chuàng)建成功"

1.2 雙分支if條件語句

語法:

if [ 條件判斷式 ]

then

條件成立時(shí),執(zhí)行的程序

else

條件不成立時(shí),執(zhí)行的另一個(gè)程序

fi

案例1:備份MySQL數(shù)據(jù)庫(kù)

[root@localhost ~]$ vi sh/bakmysql.sh

#!/bin/bash

#備份mysql數(shù)據(jù)庫(kù)。

 

ntpdate asia.pool.ntp.org &>/dev/null

#同步系統(tǒng)時(shí)間

date=$(date +%y%m%d)

#把當(dāng)前系統(tǒng)時(shí)間按照“年月日”格式賦子變量date

size=$(du -sh /var/lib/mysql)

#統(tǒng)計(jì)mysql數(shù)據(jù)庫(kù)的大小,并把大小賦予size變量

 

if [ -d /tmp/dbbak ]

#判斷備份目錄是否存在,是否為目錄

then

#如果判斷為真,執(zhí)行以下腳本

echo "Date : $date!" > /tmp/dbbak/dbinfo.txt

#把當(dāng)前日期寫入臨時(shí)文件

echo "Data size : $size" >> /tmp/dbbak/dbinfo.txt

#把數(shù)據(jù)庫(kù)大小寫入臨時(shí)文件

cd /tmp/dbbak

 

#進(jìn)入備份目錄

tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &> /dev/null

#打包壓縮數(shù)據(jù)庫(kù)與臨時(shí)文件,把所有輸出丟入垃圾箱(不想看到任何輸出)

rm -rf /tmp/dbbak/dbinfo.txt

#刪除臨時(shí)文件

else

mkdir /tmp/dbbak

#如果判斷為假,則建立備份目錄

echo "Date : $date!" > /tmp/dbbak/dbinfo.txt

echo "Data size : $size" >> /tmp/dbbak/dbinfo.txt

#把日期和數(shù)據(jù)庫(kù)大小保存如臨時(shí)文件

cd /tmp/dbbak

tar -zcf mysql-lib-$date.tar. gz dbinfo.txt /var/lib/mysql &> /dev/null

#壓縮備份數(shù)據(jù)庫(kù)與臨時(shí)文件

rm -rf/tmp/dbbak/dbinfo.txt

#刪除臨時(shí)文件

fi

案例2:判斷Apache是否啟動(dòng),如果沒有啟動(dòng)則自動(dòng)啟動(dòng)

[root@localhost ~]$ vi sh/autostart.sh

#!/bin/bash

#判斷apache是否啟動(dòng),如果沒有啟動(dòng)則自動(dòng)啟動(dòng)

 

port=$(nmap -sT 192.168.4.210 | grep tcp | grep http | awk '{print $2}')

#使用nmap命令掃描服務(wù)器,并截取 apache服務(wù)的狀態(tài),賦予變量port

#只要狀態(tài)是open,就證明正常啟動(dòng)

if [ "$port" == "open"]

#如果變量port的值是“open”

then

echo "$(date) httpd is ok!” >> /tmp/autostart-acc.log

#則證明apache 正常啟動(dòng),在正常日志中寫入一句話即可

else

/etc/rc.d/init.d/httpd start &>/dev/null

#否則證明apache沒有啟動(dòng),自動(dòng)啟動(dòng)apache

echo "$(date) restart httpd !!" >> /tmp/autostart-err.log

#并在錯(cuò)誤日志中記錄自動(dòng)啟動(dòng)apche 的時(shí)間

fi

nmap端口掃描命令,格式如下:

[root@localhost ~]$ nmap -sT 域名或IP

選項(xiàng):

-s 掃描

-T 掃描所有開啟的TCP端口

 

#知道了nmap命令的用法,我們?cè)谀_本中使用的命令就是為了截取http的狀態(tài),只要狀態(tài)是“or.

 

#就證明apache啟動(dòng)正常,否則證明apache啟動(dòng)錯(cuò)誤。來看看腳本中命令的結(jié)果:

[root@localhost ~]$ nmap -sT 192.168.4.210 | grep tcp | grep http | awk ' fprint $2}’

#掃描指定計(jì)算機(jī),提取包含tcp 的行,在提取包含httpd 的行,截取第二列open

#把截取的值賦予變量port

1.3 多分支if條件語句

語法:

if [ 條件判斷式1 ]

then

當(dāng)條件判斷式1成立時(shí),執(zhí)行程序1

elif [ 條件判斷式2 ]

then

當(dāng)條件判斷式2成立時(shí),執(zhí)行程序2

…省略更多條件…

else

當(dāng)所有條件都不成立時(shí),最后執(zhí)行此程序

fi

案例:判斷用戶輸入的是什么文件

[root@localhost ~]$ vi sh/if-elif.sh

#!/bin/bash

#判斷用戶輸入的是什么文件

 

read -p "Please input a filename: " file

#接收鍵盤的輸入,并賦予變量file

if [ -z "$file” ]

#判斷file變量是否為空

then

echo "Error, please input a filename"

#如果為空,執(zhí)行程序1,也就是輸出報(bào)錯(cuò)信息

exit 1

#退出程序,并返回值為Ⅰ(把返回值賦予變量$P)

elif [ ! -e "$file” ]

#判斷file的值是否存在

then

echo "Your input is not a file!"

#如1果不存在,則執(zhí)行程序2

exit 2

#退出程序,把并定義返回值為2

elif [ -f "$file” ]

#判斷file的值是否為普通文件

then

echo "$file is a regulare file!”

#如果是普通文件,則執(zhí)行程序3

elif [ -d "$file” ]

#到斷file的值是否為目錄文件

then

echo "$file is a directory!"

#如果是目錄文件,網(wǎng)執(zhí)行程序4

else

echo "$file is an other file!”

#如果以上判斷都不是,則執(zhí)行程序5

fi

2. 多分支case條件語句

case語句和if…elif…else語句一樣都是多分支條件語句,不過和if多分支條件語句不同的是,case語句只能判斷一種條件關(guān)系,而if語句可以判斷多種條件關(guān)系。

語法:

case $變量名 in

"值1")

如果變量的值等于值1,則執(zhí)行程序1

;;

"值2")

如果變量的值等于值2,則執(zhí)行程序2

::

…省略其他分支…

*)

如果變量的值都不是以上的值,則執(zhí)行此程序

;;

esac

這個(gè)語句需要注意以下內(nèi)容:

l case語句,會(huì)取出變量中的值,然后與語句體中的值逐一比較。如果數(shù)值符合,則執(zhí)行對(duì)應(yīng)的程序,如果數(shù)值不符,則依次比較下一個(gè)值。如果所有的值都不符合,則執(zhí)行 “*)” (*代表所有其他值)中的程序。

l case語句以“case”開頭,以“esac”結(jié)尾。

每一個(gè)分支程序之后要通過“;;”雙分號(hào)結(jié)尾,代表該程序段結(jié)束(千萬不要忘記,每次寫case語句,都不要忘記雙分號(hào))。

案例:

[root@localhost ~]$ vi sh/if-case.sh

#!/bin/bash

read -p "請(qǐng)輸入一個(gè)字符,并按Enter確認(rèn):" KEY

case "$KEY" in

[a-z]|[A-Z])

echo "您輸入的是字母"

;;

 

[0-9])

echo "您輸入的是數(shù)字"

;;

 

*)

echo "您輸入的是其他字符"

;;

esac

3. for循環(huán)

for循環(huán)是固定循環(huán),也就是在循環(huán)時(shí)已經(jīng)知道需要進(jìn)行幾次的循環(huán),有時(shí)也把for循環(huán)稱為計(jì)數(shù)循環(huán)。for的語法有如下兩種:

語法一:

for 變量 in 值1 值2 值3 …(可以是一個(gè)文件等)

do

程序

done

 

這種語法中for循環(huán)的次數(shù),取決于in后面值的個(gè)數(shù)(空格分隔),有幾個(gè)值就循環(huán)幾次,并且每次循環(huán)都把值賦予變量。

也就是說,假設(shè)in后面有三個(gè)值,for會(huì)循環(huán)三次,第一次循環(huán)會(huì)把值1賦予變量,第二次循環(huán)會(huì)把值2賦予變量,以此類推。

語法二:

for (( 初始值;循環(huán)控制條件;變量變化 ))

do

程序

done

 

語法二中需要注意:

初始值:在循環(huán)開始時(shí),需要給某個(gè)變量賦予初始值,如i=1;

 

循環(huán)控制條件:用于指定變量循環(huán)的次數(shù),如i<=100,則只要i的值小于等于100,循環(huán)就會(huì)繼續(xù);

 

變量變化:每次循環(huán)之后,變量該如何變化,如i=i+1。代表每次循環(huán)之后,變量i的值都加1。

語法一舉例:打印時(shí)間

[root@localhost ~]$ vi sh/for.sh

#!/bin/bash

#打印時(shí)間

 

for time in morning noon afternoon evening

do

echo "This time is $time!"

done

語法一舉例:批量解壓縮腳本

[root@localhost ~]$ vi sh/auto-tar. sh

#!/bin/bash

#批量解壓縮腳本

 

cd/lamp

#進(jìn)入壓縮包目錄

ls *.tar.gz > ls.log

#把所有.tar.gz結(jié)尾的文件的文件覆蓋到ls.log 臨時(shí)文件中

for i in $(cat ls.log) `

#或者這樣寫for i in `cat ls.log`

 

#讀取ls.log文件的內(nèi)容,文件中有多少個(gè)值,就會(huì)循環(huán)多少次,每次循環(huán)把文件名賦予變量i

do

tar -zxf $i &>/dev/null

#加壓縮,并把所有輸出都丟棄

done

rm -rf /lamp/ls.log

#刪除臨時(shí)文件ls.log

語法二舉例:從1加到100

[root@localhost ~]$ vi sh/add. sh

#!/bin/bash

#從1加到100

 

s=0

for (( i=1;i<=100;i=i+1 ))

#定義循環(huán)100 次

do

s=$(( $s+$i ))

#每次循環(huán)給變量s賦值

done

echo "The sum of 1+2+...+100 is : $s"

#輸出1加到100的和

語法二舉例:批量添加指定數(shù)量的用戶

[root@localhost ~]$ vi useradd.sh

#!/bin/bash

#批量添加指定數(shù)量的用戶

 

read -p "Please input user name: " -t 30 name

#讓用戶輸入用戶名,把輸入保存入變量name

 

read -p "Please input the number of users: " -t 30 num

#讓用戶輸入添加用戶的數(shù)量,把輸入保存入變量num

 

read -p "Please input the password of users: " -t 30 pass

#讓用戶輸入初始密碼,把輸入保存如變量pass

 

if [ ! -z "$name" -a ! -z "$num"-a ! -z "$pass"]

#判斷三個(gè)變量不為空

then

y=$(echo $num | sed 's/[0-9]//g')

#定義變量的值為后續(xù)命令的結(jié)果

#后續(xù)命令作用是,把變量num 的值替換為空。如果能替換為空,證明num 的值為數(shù)字

#如果不能替換為空,證明num的值為非數(shù)字。我們使用這種方法判斷變量num 的值為數(shù)字

if [ -z "$y"]

#如果變量y的值為空,證明num變量是數(shù)字

then

for (( i=1 ; i<=$num; i=i+1 ))

#循環(huán)num變量指定的次數(shù)

do

/usr/sbin/useradd $name$i &>/dev/null

#添加用戶,用戶名為變量name 的值加變量i的數(shù)字

echo $pass | /usr/bin/passwd --stdin $name$i &>/dev/null

#給用戶設(shè)定初始密碼為變量pass 的值

done

fi

fi

語法二舉例:批量刪除用戶

[root@localhost ~]$ vi sh/userdel.sh

#!/bin/bash

#批量刪除用戶

 

user=$(cat /etc/passwd | grep " /bin/bash"|grep -v "root"Icut -d ":" -f 1)

#讀取用戶信息文件,提取可以登錄用戶,取消root用戶,截取第一列用戶名

 

for i in $user

#循環(huán),有多少個(gè)普通用戶,循環(huán)多少次

do

userdel -r $i

#每次循環(huán),刪除指定普通用戶

done

4. while循環(huán)

語法:

while [ 條件判斷式 ]

do

程序

done

案例:1加到100

[root@localhost ~]$ vi sh/addnum.sh

#!/bin/bash

#從1加到100

 

i=1

s=0

#給變量i和變量s賦值

 

while [ $i -le 100 ]

#如果變量i的值小于等于100,則執(zhí)行循環(huán)

do

s=$(( $s+$i ))

i=$(( $i+1 ))

done

echo "The sum is: $s"

案例:輸入的數(shù)值進(jìn)行比較判斷

[root@localhost ~]$ vi sh/addnum.sh

#!/bin/bash

PRICE=$(expr $RANDOM % 1000)

TIMES=0

 

echo "商品的價(jià)格為0-999之間,猜猜看是多少?"

while true

do

read -p "請(qǐng)輸入您猜的價(jià)格:" INT

let TIMES++

 

if [ $INT -eq $PRICE ] ; then

echo "恭喜您猜對(duì)了,實(shí)際價(jià)格是 $PRICE"

echo "您總共猜了 $TIMES 次"

exit 0

elif [ $INT -gt $PRICE ] ; then

echo "太高了"

else

echo "太低了"

fi

done

5. until循環(huán)

和while循環(huán)相反,until循環(huán)時(shí)只要條件判斷式不成立則進(jìn)行循環(huán),并執(zhí)行循環(huán)程序。一旦循環(huán)條件成立,則終止循環(huán)。

語法:

until [ 條件判斷式 ]

do

程序

done

案例一:1加到100

[root@localhost ~]$ vi sh/until.sh

#!/bin/bash

#從1加到100

 

i=1

s=0

#t給變量i和變量s賦值

 

until [ $i -gt 100 ]

#循環(huán)直到變量i的值大于100,就停止循環(huán)

do

s=$(( $s+$i ))

i=$(( $i+1 ))

done

echo "The sum is: $s"

6. 函數(shù)

語法:

function 函數(shù)名 () {

程序

}

案例:接收用戶輸入的數(shù)字,然后從1加到這個(gè)數(shù)字

[root@localhost ~]$ vi sh/function.sh

#!/bin/bash

#接收用戶輸入的數(shù)字,然后從1加到這個(gè)數(shù)字

 

function sum () {

#定義函數(shù)sum

s=0

for (( i=0; i<=$num;i=i+1 ))

#循環(huán)直到i大于$1為止。$1是函數(shù)sum 的第一個(gè)參數(shù)

#在函數(shù)中也可以使用位置參數(shù)變量,不過這里的$1指的是函數(shù)的第一個(gè)參數(shù)

do

s=$(( $i+$s ))

done

echo "The sum of 1+2+3...+$1 is :$s"

#輸出1加到$1的和

}

 

read -p "Please input a number: " -t 30 num

#接收用戶輸入的數(shù)字,并把值賦予變量num

y=$(echo $num | sed 's/[0-9]//g')

#把變量num的值替換為空,并賦予變量y

 

if [ -z "$y"]

#判斷變量y是否為空,以確定變量num中是否為數(shù)字

then

sum $num

#調(diào)用sum函數(shù),并把變量num的值作為第一個(gè)參數(shù)傳遞給sum函數(shù)

else

echo "Error!! Please input a number!"

#如果變量num 的值不是數(shù)字,則輸出報(bào)錯(cuò)信息

fi

7. 特殊流程控制語句

7.1 exit語句

系統(tǒng)是有exit命令的,用于退出當(dāng)前用戶的登錄狀態(tài)。可是在Shell腳本中,exit語句是用來退出當(dāng)前腳本的。也就是說,在Shell腳本中,只要碰到了exit語句,后續(xù)的程序就不再執(zhí)行,而直接退出腳本。

exit的語法如下:

exit [返回值]

如果exit命令之后定義了返回值,那么這個(gè)腳本執(zhí)行之后的返回值就是我們自己定義的返回值。可以通過查詢$?這個(gè)變量,來查看返回值。如果exit之后沒有定義返回值,腳本執(zhí)行之后的返回值是執(zhí)行exit 語句之前,最后執(zhí)行的一條命令的返回值。寫一個(gè)exit 的例子:

[root@localhost ~]$ vi sh/exit.sh

#!/bin/bash

#演示exit的作用

 

read -p "Please input a number: " -t 30 num

#接收用戶的輸入,并把輸入賦予變量num

y=$ (echo $num | sed 's/[0-9]//g')

#如果變量num 的值是數(shù)字,則把num的值替換為空,否則不替換

#把替換之后的值賦予變量y

[ -n "$y" ] && echo "Error! Please input a number!" && exit 18

#判斷變量y的值如果不為空,輸出報(bào)錯(cuò)信息,退出腳本,退出返回值為18

echo "The number is: $num"

#如果沒有退出加班,則打印變量num中的數(shù)字

7.2 break語句

當(dāng)程序執(zhí)行到break語句時(shí),會(huì)結(jié)束整個(gè)當(dāng)前循環(huán)。而continue 語句也是結(jié)束循環(huán)的語句,不過continue 語句單次當(dāng)前循環(huán),而下次循環(huán)會(huì)繼續(xù)。

案例:

[root@localhost ~]$ vi sh/break.sh

#!/bin/bash

#演示break 跳出循環(huán)

 

for (( i=1;i<=10; i=i+1 ))

#循環(huán)十次

do

if ["$i" -eq 4 ]

#如果變量i的值等于4

then

break

#退出整個(gè)循環(huán)

fi

echo $i

#輸出變量i的值

done

執(zhí)行下這個(gè)腳本,因?yàn)橐坏┳兞縤的值等于4,整個(gè)循環(huán)都會(huì)跳出,所以應(yīng)該只能循環(huán)三次:

[root@localhost ~]$ chmod 755 sh/break.sh

[root@localhost ~]#sh/break.sh

1

2

3

7.3 continue語句

continue也是結(jié)束流程控制的語句。如果在循環(huán)中,continue語句只會(huì)結(jié)束單次當(dāng)前循環(huán)。

案例:

[root@localhost ~]$ vi sh/break.sh

#!/bin/bash

#演示continue

 

for (( i=1;i<=10;i=i+1 ))

#循環(huán)十次

do

if ["$i" -eq 4 ]

#如果變量i的值等于4

then

continue

#退出換成continue

fi

echo $i

#輸出變量i的值

done

執(zhí)行下這個(gè)腳本:

[root@localhost ~]$ chmod 755 sh/continue.sh

[root@localhost ~]#sh/break.sh

1

2

3

5

6

7

8

9

10

#少了4這個(gè)輸出

六、字符截取、替換和處理命令

正則表達(dá)式

 

元字符

 

描述

 

示例

 

 

轉(zhuǎn)義符,將特殊字符進(jìn)行轉(zhuǎn)義,忽略其特殊意義

 

a.b匹配a.b,但不能匹配ajb,.被轉(zhuǎn)義為特殊意義

 

^

 

匹配行首,awk中,^則是匹配字符串的開始

 

^tux匹配以tux開頭的行

 

$

 

匹配行尾,awk中,$則是匹配字符串的結(jié)尾

 

tux$匹配以tux結(jié)尾的行

 

.

 

匹配除換行符n之外的任意單個(gè)字符

 

ab.匹配abc或abd,不可匹配abcd或abde,只能匹配單字符

 

[ ]

 

匹配包含在[字符]之中的任意一個(gè)字符

 

coo[kl]可以匹配cook或cool

 

[^]

 

匹配[^字符]之外的任意一個(gè)字符

 

123[^45]不可以匹配1234或1235,1236、1237都可以

 

[-]

 

匹配[]中指定范圍內(nèi)的任意一個(gè)字符,要寫成遞增

 

[0-9]可以匹配1、2或3等其中任意一個(gè)數(shù)字

 

?

 

匹配之前的項(xiàng)1次或者0次

 

colou?r可以匹配color或者colour,不能匹配colouur

 

+

 

匹配之前的項(xiàng)1次或者多次

 

sa-6+匹配sa-6、sa-666,不能匹配sa-

 

*

 

匹配之前的項(xiàng)0次或者多次

 

co*l匹配cl、col、cool、coool等

 

()

 

匹配表達(dá)式,創(chuàng)建一個(gè)用于匹配的子串

 

ma(tri)?匹配max或maxtrix

 

{n}

 

匹配之前的項(xiàng)n次,n是可以為0的正整數(shù)

 

[0-9]{3}匹配任意一個(gè)三位數(shù),可以擴(kuò)展為[0-9][0-9][0-9]

 

{n,}

 

之前的項(xiàng)至少需要匹配n次

 

[0-9]{2,}匹配任意一個(gè)兩位數(shù)或更多位數(shù)不支持{n,}{n,}{n,}

 

{n,m}

 

指定之前的項(xiàng)至少匹配n次,最多匹配m次,n<=m

 

[0-9]{2,5}匹配從兩位數(shù)到五位數(shù)之間的任意一個(gè)數(shù)字

 

|

 

交替匹配|兩邊的任意一項(xiàng)

 

ab(c|d)匹配abc或abd

1 字符截取、替換命令

1.1 cut 列提取命令

[root@localhost ~]$ cut [選項(xiàng)] 文件名

選項(xiàng):

-f 列號(hào): 提取第幾列

-d 分隔符: 按照指定分隔符分割列

-n取消分割多字節(jié)字符

-c 字符范圍: 不依賴分隔符來區(qū)分列,而是通過字符范圍(行首為0)來進(jìn)行字段提取。“n-”表示從第n個(gè)字符到行尾;“n-m”從第n個(gè)字符到第m個(gè)字符;“一m”表示從第1個(gè)字符到第m個(gè)字符。

--complement補(bǔ)足被選擇的字節(jié)、字符或字段

--out-delimiter指定輸出內(nèi)容是的字段分割符

cut命令的默認(rèn)分隔符是制表符,也就是“tab”鍵,不過對(duì)空格符可是支持的不怎么好啊。我們先建立一個(gè)測(cè)試文件,然后看看cut命令的作用吧:

[root@localhost ~]$ vi student.txt

idnamegendermark

1limingm86

2scm67

3tgn90

[root@localhost ~]$ cut -f 2 student.txt

#提取第二列內(nèi)容

那如果想要提取多列呢?只要列號(hào)直接用“,”分開,命令如下:

[root@localhost ~]$ cut -f 2,3 student.txt

如果我想用cut命令截取df命令的第一列和第三列,就會(huì)出現(xiàn)這樣的情況:

[root@localhost~]$ df -h | cut -d " " -f 1,3

Filesystem

/dev/sda2

tmpfs

/dev/sda1

1.2 awk 編程

參考:

linux文本處理三劍客:grep,sed及awk

1.2.1 awk 概述

AWK 是一種處理文本文件的語言,是一個(gè)強(qiáng)大的文本分析工具。

1.2.2 printf 格式化輸出

[root@localhost ~]$ printf ‘輸出類型輸出格式’ 輸出內(nèi)容

 

輸出類型:

%c: ASCII字符.顯示相對(duì)應(yīng)參數(shù)的第一個(gè)字符

%-ns: 輸出字符串,減號(hào)“-”表示左對(duì)齊(默認(rèn)右對(duì)齊),n是數(shù)字指代輸出幾個(gè)字符,幾個(gè)參數(shù)就寫幾個(gè)%-ns

%-ni: 輸出整數(shù),n是數(shù)字指代輸出幾個(gè)數(shù)字

%f: 輸出小數(shù)點(diǎn)右邊的位數(shù)

%m.nf: 輸出浮點(diǎn)數(shù),m和n是數(shù)字,指代輸出的整數(shù)位數(shù)和小數(shù)位數(shù)。如%8.2f代表共輸出8位數(shù),其中2位是小數(shù),6位是整數(shù)。

 

輸出格式:

a: 輸出警告聲音

b: 輸出退格鍵,也就是Backspace鍵

f: 清除屏幕

n: 換行

r: 回車,也就是Enter鍵

t: 水平輸出退格鍵,也就是Tab 鍵

v: 垂直輸出退格鍵,也就是Tab 鍵

為了演示printf命令,我們需要修改下剛剛cut命令使用的student.txt文件,文件內(nèi)容如下:

[root@localhost ~]$ vi student.txt

ID Name php Linux MySQL Average

1 AAA 66 66 66 66

2 BBB 77 77 77 77

3 CCC 88 88 88 88

 

#printf格式輸出文件

[root@localhost ~]$ printf '%st %st %st %st %st %st n’ $(cat student.txt)

#%s分別對(duì)應(yīng)后面的參數(shù),6列就寫6個(gè)

ID Name php Linux MySQL Average

1 AAA 66 66 66 66

2 BBB 77 77 77 77

3 CCC 88 88 88 88

如果不想把成績(jī)當(dāng)成字符串輸出,而是按照整型和浮點(diǎn)型輸出,則要這樣:

[root@localhost ~]$ printf '%it %st %it %it %it %8.2ft n’ $(cat student.txt | grep -v Name)

1.2.3 awk 基本使用

[root@localhost ~]$ awk‘條件1{動(dòng)作1} 條件2{動(dòng)作2}…’ 文件名

條件(Pattern):

一般使用關(guān)系表達(dá)式作為條件。這些關(guān)系表達(dá)式非常多,例如:

x > 10 判斷變量x是否大于10

x == y 判斷變量x是否等于變量y

A ~ B 判斷字符串A中是否包含能匹配B表達(dá)式的子字符串

A !~ B 判斷字符串A中是否不包含能匹配B表達(dá)式的子字符串

 

動(dòng)作(Action) :

格式化輸出

流程控制語句

 

常用參數(shù):

 

-F指定輸入時(shí)用到的字段分隔符

-v自定義變量

-f從腳本中讀取awk命令

-m對(duì)val值設(shè)置內(nèi)在限制

我們這里先來學(xué)習(xí)awk基本用法,也就是只看看格式化輸出動(dòng)作是干什么的。

[root@localhost ~]$ awk '{printf $2 "t" $6 "n"}’ student.txt

#輸出第二列和第六列

比如剛剛截取df命令的結(jié)果時(shí),cut命令已經(jīng)力不從心了,我們來看看awk命令:

[root@localhost ~]$ df -h | awk '{print $1 "t" $3}'

#截取df命令的第一列和第三列

1.2.4 awk 的條件

 

條件的類型

 

條件

 

說明

 

awk保留字

 

BEGIN

 

在awk程序一開始時(shí),尚未讀取任何數(shù)據(jù)之前執(zhí)行。BEGIN后的動(dòng)作只在程序開始時(shí)執(zhí)行一次

 

awk保留字

 

END

 

在awk程序處理完所有數(shù)據(jù),即將結(jié)束時(shí)執(zhí)行。END后的動(dòng)作只在程序結(jié)束時(shí)執(zhí)行一次

 

關(guān)系運(yùn)算符

 

>

 

大于

 

關(guān)系運(yùn)算符

 

<

 

小于

 

關(guān)系運(yùn)算符

 

>=

 

大于等于

 

關(guān)系運(yùn)算符

 

<=

 

小于等于

 

關(guān)系運(yùn)算符

 

==

 

等于。用于判斷兩個(gè)值是否相等,如果是給變量賦值,請(qǐng)使用“”號(hào)

 

關(guān)系運(yùn)算符

 

!=

 

不等于

 

關(guān)系運(yùn)算符

 

A~B

 

判斷字符串A中是否包含能匹配B表達(dá)式的子字符串

 

關(guān)系運(yùn)算符

 

A!~B

 

判斷字符串A中是否不包含能匹配B表達(dá)式的子字符串

 

正則表達(dá)式

 

/正則/

 

如果在"//"中可以寫入字符,也可以支持正則表達(dá)式

BEGIN

BEGIN是awk的保留字,是一種特殊的條件類型。BEGIN的執(zhí)行時(shí)機(jī)是“在 awk程序一開始時(shí),尚未讀取任何數(shù)據(jù)之前執(zhí)行”。一旦BEGIN后的動(dòng)作執(zhí)行一次,當(dāng)awk開始從文件中讀入數(shù)據(jù),BEGIN的條件就不再成立,所以BEGIN定義的動(dòng)作只能被執(zhí)行一次。

例如:

[root@localhost ~]$ awk 'BEGIN{printf "This is a transcript n" } {printf $2 "t" $6 "n"}’ student.txt

#awk命令只要檢測(cè)不到完整的單引號(hào)不會(huì)執(zhí)行,所以這個(gè)命令的換行不用加入“|”,就是一行命令

#這里定義了兩個(gè)動(dòng)作

#第一個(gè)動(dòng)作使用BEGIN條件,所以會(huì)在讀入文件數(shù)據(jù)前打印“這是一張成績(jī)單”(只會(huì)執(zhí)行一次)

#第二個(gè)動(dòng)作會(huì)打印文件的第二字段和第六字段

END

END也是awk保留字,不過剛好和BEGIN相反。END是在awk程序處理完所有數(shù)據(jù),即將結(jié)束時(shí)執(zhí)行。END后的動(dòng)作只在程序結(jié)束時(shí)執(zhí)行一次。例如:

[root@localhost ~]$ awk 'END{printf "The End n"} {printf $2 "t" $6 "n"}’ student.txt

#在輸出結(jié)尾輸入“The End”,這并不是文檔本身的內(nèi)容,而且只會(huì)執(zhí)行一次

關(guān)系運(yùn)算符

舉幾個(gè)例子看看關(guān)系運(yùn)算符。假設(shè)我想看看平均成績(jī)大于等于87分的學(xué)員是誰,就可以這樣輸入命令:

例子1:

[root@localhost ~]$ cat student.txt | grep -v Name | awk '$6 >= 87 {printf $2 "n"}'

#使用cat輸出文件內(nèi)容,用grep取反包含“Name”的行

#判斷第六字段(平均成績(jī))大于等于87分的行,如果判斷式成立,則打第六列(學(xué)員名$2)

加入了條件之后,只有條件成立動(dòng)作才會(huì)執(zhí)行,如果條件不滿足,則動(dòng)作則不運(yùn)行。通過這個(gè)實(shí)驗(yàn),大家可以發(fā)現(xiàn),雖然awk是列提取命令,但是也要按行來讀入的。這個(gè)命令的執(zhí)行過程是這樣的:

1)如果有BEGIN條件,則先執(zhí)行BEGIN定義的動(dòng)作。

2)如果沒有BEGIN條件,則讀入第一行,把第一行的數(shù)據(jù)依次賦予$0、$1、$2等變量。其中$0代表此行的整體數(shù)據(jù),$1代表第一字段,$2代表第二字段。

3)依據(jù)條件類型判斷動(dòng)作是否執(zhí)行。如果條件符合,則執(zhí)行動(dòng)作,否則讀入下一行數(shù)據(jù)。如果沒有條件,則每行都執(zhí)行動(dòng)作。

4)讀入下一行數(shù)據(jù),重復(fù)執(zhí)行以上步驟。

再舉個(gè)例子,如果我想看看Sc用戶的平均成績(jī)呢:

例子2:

[root@localhost ~]$ awk '$2 ~ /AAA/ {printf $6 "n"}' student.txt

#如果第二字段中輸入包含有“Sc”字符,則打印第六字段數(shù)據(jù)

85.66

這里要注意在awk中,使用“//”包含的字符串,awk命令才會(huì)查找。也就是說字符串必須用“//”包含,awk命令才能正確識(shí)別。

正則表達(dá)式

如果要想讓awk 識(shí)別字符串,必須使用“//”包含,例如:

例子1:

[root@localhost ~]$ awk '/Liming/ {print}’student.txt

#打印Liming的成績(jī)

當(dāng)使用df命令查看分區(qū)使用情況是,如果我只想查看真正的系統(tǒng)分區(qū)的使用狀況,而不想查看光盤和臨時(shí)分區(qū)的使用狀況,則可以:

例子2:

[root@localhost ~]$ df -h | awk '/sda[O-9]/ {printf $1 "t" $5 "n"}’

#查詢包含有sda數(shù)字的行,并打印第一字段和第五字段

1.2.5 awk 內(nèi)置變量

 

awk內(nèi)置變量

 

作用

 

$0

 

代表目前awk所讀入的整行數(shù)據(jù)。我們已知awk是一行一行讀入數(shù)據(jù)的,$0就代表當(dāng)前讀入行的整行數(shù)據(jù)。

 

$n

 

代表目前讀入行的第n個(gè)字段。比如,

$1表示第1個(gè)字段(列),$

2表示第2個(gè)字段(列),如此類推

 

NF

 

當(dāng)前行擁有的字段(列)總數(shù)。

 

NR

 

當(dāng)前awk所處理的行,是總數(shù)據(jù)的第幾行。

 

FS

 

用戶定義分隔符。awk的默認(rèn)分隔符是任何空格,如果想要使用其他分隔符(如“:”),就需要FS變量定義。

 

ARGC

 

命令行參數(shù)個(gè)數(shù)。

 

ARGV

 

命令行參數(shù)數(shù)組。

 

FNR

 

當(dāng)前文件中的當(dāng)前記錄數(shù)(對(duì)輸入文件起始為1)。

 

OFMT

 

數(shù)值的輸出格式(默認(rèn)為%.6g)。

 

OFS

 

輸出字段的分隔符(默認(rèn)為空格)。

 

ORS

 

輸出記錄分隔符(默認(rèn)為換行符)。

 

RS

 

輸入記錄分隔符(默認(rèn)為換行符)。

awk常用統(tǒng)計(jì)實(shí)例

1、打印文件的第一列(域) :

awk '{print $1}' filename

 

2、打印文件的前兩列(域) :

awk '{print $1,$2}' filename

 

3、打印完第一列,然后打印第二列 :

awk '{print $1 $2}' filename

 

4、打印文本文件的總行數(shù) :

awk 'END{print NR}' filename

 

5、打印文本第一行 :

awk 'NR==1{print}' filename

 

6、打印文本第二行第一列 :

sed -n "2, 1p" filename | awk 'print $1'

 

1. 獲取第一列

ps -aux | grep watchdog | awk '{print $1}'

 

2. 獲取第一列,第二列,第三列

ps -aux | grep watchdog | awk '{print $1, $2, $3}'

 

3. 獲取第一行的第一列,第二列,第三列

ps -aux | grep watchdog | awk 'NR==1{print $1, $2, $3}'

 

4. 獲取行數(shù)NR

df -h | awk 'END{print NR}'

 

5. 獲取列數(shù)NF(這里是獲取最后一行的列數(shù),注意每行的列數(shù)可能是不同的)

ps -aux | grep watchdog | awk 'END{print NF}'

 

6. 獲取最后一列

ps -aux | grep watchdog | awk '{print $NF}'

 

7. 對(duì)文件進(jìn)行操作

awk '{print $1}' fileName

 

8. 指定分隔符(這里以:分割)

ps -aux | grep watchdog |awk -F':' '{print $1}'

 

9. 超出范圍不報(bào)錯(cuò)

ps -aux | grep watchdog | awk '{print $100}'

 

[root@localhost ~]$ cat /etc/passwd | grep "/bin/bash" | awk '{FS=":"} {printf $1 "t" $3 "n"}’

#查詢可以登錄的用戶的用戶名和UID

這里“:”分隔符生效了,可是第一行卻沒有起作用,原來我們忘記了“BEGIN”條件,那么再來試試;

[root@localhost ~]$ cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {printf $1 "t" $3 "n"}’

 

[root@localhost ~]$ cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {printf $1 "t" $3 "t 行號(hào):” NR "t 字段數(shù):" NF "n"}’

#解釋下awk命令

#開始執(zhí)行{分隔符是“:”}{輸出第一字段和第三字段輸出行號(hào)(NR值)字段數(shù)(NF值)}

root 0 行號(hào):1 字段數(shù):7

user1 501 行號(hào):2 字段數(shù):7

如果我只想看看sshd這個(gè)偽用戶的相關(guān)信息,則可以這樣使用:

[root@localhost ~]$ cat /etc/passwd | awk 'BEGIN {FS=":"} $1=="sshd" {printf $1 "t" $3 "t 行號(hào):" NR "t 字段數(shù):" NF "n"}’

#可以看到sshd 偽用戶的UID是74,是/etc/passwd_文件的第28行,此行有7個(gè)字段

1.2.6 awk 流程控制

我們?cè)賮砝孟聅tudent.txt文件做個(gè)練習(xí),后面的使用比較復(fù)雜,我們?cè)倏纯催@個(gè)文件的內(nèi)容:

[root@localhost ~]$ cat student.txt

ID Name php Linux MySQL Average

1 AAA 66 66 66 66

2 BBB 77 77 77 77

3 CCC 88 88 88 88

我們先來看看該如何在awk中定義變量與調(diào)用變量的值。假設(shè)我想統(tǒng)計(jì)PHP成績(jī)的總分,那么就應(yīng)該這樣:

[root@localhost ~]$ awk 'NR==2 {php1=$3}

NR==3 {php2=$3}

NR==4 {php3=$3;totle=phpl+php2+php3;print "totle php is " totle}’ student.txt

#統(tǒng)計(jì)PHIP成績(jī)的總分

我們解釋下這個(gè)命令。

"NR==2 {php1=$3}" (條件是NR==2,動(dòng)作是php1=$3)這句話是指如果輸入數(shù)據(jù)是第二行(第一行是標(biāo)題行),就把第二行的第三字段的值賦予變量"php1"。

"NR==3 {php2=$3}" 這句話是指如果輸入數(shù)據(jù)是第三行,就把第三行的第三字段的值賦予變量"php2"。

"NR==4 {php3=$3;totle=phpl+php2+php3;print "totle php is " totle}"("NR==4"是條件,后面{}中的都是動(dòng)作)這句話是指如果輸入數(shù)據(jù)是第四行﹐就把第四行的第三字段的值賦予變量"php3";然后定義變量totle的值是"php1+php2+php3";然后輸出"totle php is"關(guān)鍵字,后面加變量totle的值。

在awk編程中,因?yàn)槊钫Z句非常長(zhǎng),在輸入格式時(shí)需要注意以下內(nèi)容:

l 多個(gè)條件 {動(dòng)作} 可以用空格分割,也可以用回車分割。

l 在一個(gè)動(dòng)作中,如果需要執(zhí)行多個(gè)命令,需要用 “;” 分割,或用回車分割。

l 在awk中,變量的賦值與調(diào)用都不需要加入“$”符。

l 條件中判斷兩個(gè)值是否相同,請(qǐng)使用 “==”,以便和變量賦值進(jìn)行區(qū)分。

在看看該如何實(shí)現(xiàn)流程控制,假設(shè)如果Linux成績(jī)大于90,就是一個(gè)好男人(學(xué)PHP的表示壓力很大!) :

[root@localhost ~]$ awk '{if (NR>=2) {if ($4>60) printf $2 "is a good man!n"}}’ student.txt

#程序中有兩個(gè)if判斷,第一個(gè)判斷行號(hào)大于2,第二個(gè)判斷Linux成績(jī)大于90分

Liming is a good man !

Sc is a good man !

1.2.7 awk 函數(shù)

awk編程也允許在編程時(shí)使用函數(shù),我們講講awk的自定義函數(shù)。awk函數(shù)的定義方法如下:

function 函數(shù)名(參數(shù)列表){

函數(shù)體

}

我們定義一個(gè)簡(jiǎn)單的函數(shù),使用函數(shù)來打印student.txt的學(xué)員姓名和平均成績(jī),應(yīng)該這樣來寫函數(shù):

[root@localhost ~]$ awk 'function test(a,b) { printf a "t" b "n"}

#定義函數(shù)test,包含兩個(gè)參數(shù),函數(shù)體的內(nèi)容是輸出這兩個(gè)參數(shù)的值

{ test($2,$6) } ' student.txt

#調(diào)用函數(shù)test,并向兩個(gè)參數(shù)傳遞值。

Name Average

AAA 87.66

BBB 85.66

CCC 91.66

1.2.8 awk 中調(diào)用腳本

對(duì)于小的單行程序來說,將腳本作為命令行自變量傳遞給awk是非常簡(jiǎn)單的,而對(duì)于多行程序就比較難處理。當(dāng)程序是多行的時(shí)候,使用外部腳本是很適合的。首先在外部文件中寫好腳本,然后可以使用awk的-f選項(xiàng),使其讀入腳本并且執(zhí)行。

例如,我們可以先編寫一個(gè)awk腳本:

[root@localhost ~]$ vi pass.awk

BEGIN {FS=":"}

{ print $1 "t" $3}

然后可以使用“一f”選項(xiàng)來調(diào)用這個(gè)腳本:

[root@localhost ~]$ awk -f pass.awk /etc/passwd

rooto

bin1

daemon2

…省略部分輸出…

1.3 sed 文本選取、替換、刪除、新增的命令

sed主要是用來將數(shù)據(jù)進(jìn)行選取、替換、刪除、新增的命令。

語法:

[root@localhost ~]$ sed [選項(xiàng)] ‘[動(dòng)作]’ 文件名

 

選項(xiàng):

-n: 一般sed命令會(huì)把所有數(shù)據(jù)都輸出到屏幕,如果加入此選擇,則只會(huì)把經(jīng)過sed命令處理的行輸出到屏幕。

-e: 允許對(duì)輸入數(shù)據(jù)應(yīng)用多條sed命令編輯。

-f 腳本文件名: 從sed腳本中讀入sed操作。和awk命令的-f非常類似。

-r: 在sed中支持?jǐn)U展正則表達(dá)式。

-i: 用sed的修改結(jié)果直接修改讀取數(shù)據(jù)的文件,而不是由屏幕輸出

 

動(dòng)作:

num a : 追加,在當(dāng)前行后添加一行或多行。添加多行時(shí),除最后一行外,每行末尾需要用“”代表數(shù)據(jù)未完結(jié)。num表示第幾行

c : 行替換,用c后面的字符串替換原數(shù)據(jù)行,替換多行時(shí),除最后一行外,每行末尾需用“”代表數(shù)據(jù)未完結(jié)。

num i : 插入,在當(dāng)期行前插入一行或多行。插入多行時(shí),除最后一行外,每行末尾需要用“”代表數(shù)據(jù)未完結(jié)。num表示第幾行

d ; 刪除,刪除指定的行。

p : 打印,輸出指定的行。

s : 字串替換,用一個(gè)字符串替換另外一個(gè)字符串。格式為“行范圍s/"舊字串/新字串/g”(和vim中的替換格式類似)。

對(duì)sed命令大家要注意,sed所做的修改并不會(huì)直接改變文件的內(nèi)容(如果是用管道符接收的命令的輸出,這種情況連文件都沒有),而是把修改結(jié)果只顯示到屏幕上,除非使用“-i”選項(xiàng)才會(huì)直接修改文件。

2 字符處理命令

2.1 sort 排序命令

[root@localhost~]$ sort [選項(xiàng)] 文件名

選項(xiàng):

 

-f: 忽略大小寫

-b: 忽略每行前面的空白部分

-n: 以數(shù)值型進(jìn)行排序,默認(rèn)使用字符串型排序

-r: 反向排序

-u: 刪除重復(fù)行。就是uniq命令

-t: 指定分隔符,默認(rèn)是分隔符是制表符

-k n[,m]: ―按照指定的字段范圍排序。從第n字段開始,m字段結(jié)束(默認(rèn)到行尾)

案例:

sort命令默認(rèn)是用每行開頭第一個(gè)字符來進(jìn)行排序的,比如:

[root@localhost~]$ sort /etc/passwd

#排序用戶信息文件

如果想要反向排序,請(qǐng)使用“-r”選項(xiàng):

[root@localhost~]$ sort -r/etc/passwd

#反向排序

如果想要指定排序的字段,需要使用“-t”選項(xiàng)指定分隔符,并使用“-k”選項(xiàng)指定字段號(hào)。加入我想要按照UID字段排序/etc/passwd文件:

[root@localhost~]$ sort -t ":" -k 3,3 /etc/passwd

#指定分隔符是“:”,用第三字段開頭,第三字段結(jié)尾排序,就是只用第三字段排序

因?yàn)閟ort默認(rèn)是按照字符排序,前面用戶的UID的第一個(gè)字符都是1,所以這么排序。要想按照數(shù)字排序,請(qǐng)使用“-n”選項(xiàng):

[root@localhost~]$ sort -n -t ":" -k 3,3 /etc/passwd

當(dāng)然“-k”選項(xiàng)可以直接使用“-k 3”,代表從第三字段到行尾都排序(第一個(gè)字符先排序,如果一致,第二個(gè)字符再排序,知道行尾)。

2.2 uniq 取消重復(fù)行

uniq [-c/d/D/u/i] [-f Fields] [-s N] [-w N] [InFile] [OutFile]

參數(shù)解釋:

-c: 在每列旁邊顯示該行重復(fù)出現(xiàn)的次數(shù)。

-d: 僅顯示重復(fù)出現(xiàn)的行列,顯示一行。

-D: 顯示所有重復(fù)出現(xiàn)的行列,有幾行顯示幾行。

-u: 僅顯示出一次的行列

-i: 忽略大小寫字符的不同

-f Fields: 忽略比較指定的列數(shù)。

-s N: 忽略比較前面的N個(gè)字符。

-w N: 對(duì)每行第N個(gè)字符以后的內(nèi)容不作比較。

# uniq.txt

 

My name is Delav

My name is Delav

My name is Delav

I'm learning JAVA

I'm learning Java

I'm learning Java

who am i

Who am i

Python/ target=_blank class=infotextkey>Python is so simple

My name is Delav

That's good

That's good

And studying Golang

直接去重

uniq uniq.txt

結(jié)果為:

My name is Delav

I'm learning Java

who am i

Who am i

Python is so simple

My name is Delav

That's good

And studying Golang

顯示重復(fù)出現(xiàn)的次數(shù)

uniq -c uniq.txt 、

結(jié)果為:

3 My name is Delav

3 I'm learning Java

1 who am i

1 Who am i

1 Python is so simple

1 My name is Delav

2 That's good

1 And studying Golang

你會(huì)發(fā)現(xiàn),上面有兩行 ”My name is Delav ” 是相同的。也就是說,當(dāng)重復(fù)的行不相鄰時(shí),uniq 命令是不起作用的。所以,經(jīng)常需要跟

sort 命令一起使用。

sort uniq.txt | uniq -c

結(jié)果為:

1 And studying Golang

3 I'm learning Java

4 My name is Delav

1 Python is so simple

2 That's good

1 who am i

1 Who am i

只顯示重復(fù)的行,并顯示重復(fù)次數(shù)

uniq -cd uniq.txt

結(jié)果為:

3 My name is Delav

3 I'm learning Java

2 That's good

顯示所有重復(fù)的行,不能與 -c 一起使用

uniq -D uniq.txt

My name is Delav

My name is Delav

My name is Delav

I'm learning Java

I'm learning Java

I'm learning Java

That's good

That's good

忽略第幾列字符

下面這里 -f 1 忽略了第一列字符,所以"who am i" 和 "Who am i" 判定為重復(fù)

uniq -c -f 1 uniq.txt

結(jié)果為:

3 My name is Delav

3 I'm learning Java

2 who am i

1 Python is so simple

1 My name is Delav

2 That's good

1 And studying Golang

忽略大小寫

下面這里 -i 忽略了大小寫,所以"who am i" 和 "Who am i" 判定為重復(fù)

uniq -c -i uniq.txt

結(jié)果為:

3 My name is Delav

3 I'm learning Java

2 who am i

1 Python is so simple

1 My name is Delav

2 That's good

1 And studying Golang

忽略前面N個(gè)字符

下面這里 -s 4 表示忽略前面四個(gè)字符,所以"who am i" 和 "Who am i" 判定為重復(fù)

uniq -c -s 4 uniq.txt

結(jié)果為:

3 My name is Delav

3 I'm learning Java

2 who am i

1 Python is so simple

1 My name is Delav

2 That's good

1 And studying Golang

忽略第N個(gè)字符后的內(nèi)容

uniq -c -w 2 uniq.txt

2.3 wc 統(tǒng)計(jì)命令

[root@localhost~]$ wc [選項(xiàng)] 文件名

選項(xiàng):

-l:只統(tǒng)計(jì)行數(shù)

-w:只統(tǒng)計(jì)單詞數(shù)

-m:只統(tǒng)計(jì)字符數(shù)

分享到:
標(biāo)簽:shell
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定