高級Bash腳本編程指南_第1頁
高級Bash腳本編程指南_第2頁
高級Bash腳本編程指南_第3頁
高級Bash腳本編程指南_第4頁
高級Bash腳本編程指南_第5頁
已閱讀5頁,還剩69頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

.74/74高級Bash腳本編程指南:從一個簡單的script出發(fā)成于堅持,敗于止步開始shell腳本編程學(xué)習(xí),路途遍布荊棘啊,O<∩_∩>O~,開始吧,這是"高級Bash腳本編程指南"為我們量身打造的"HelloWorld",其實也不算,因為這個只是我們無比熟悉的命令的堆疊嘛!O<∩_∩>O清除/var/log下的log文件[html]viewplaincopy#

清除,當(dāng)然要使用root身份來運行這個腳本.

cd

/var/log

cat

/dev/null

>

messages

cat

/dev/null

>

wtmp

echo

"Logs

cleaned

up."

像分析helloworld一樣,我們也說下這個shell腳本吧!這根本就沒什么稀奇的,只不過是命令的堆積,來讓從console或者xterm中一個一個的輸入命令更方便一些.好處就是把所有命令都放在一個腳本中,不用每次都敲它們.這樣的話,這個腳本就成為了一個工具,對于特定的應(yīng)用來說,這個腳本就很容易被修改或定制.其中,第一條#后面帶一句話,你該猜到了,沒錯,這是注釋,將來你會經(jīng)常和他打交道,先見下面吧cd/var/log這簡單,我天天在用,我就別廢話了cat/dev/null>messages這個前面簡單我也天天用,不過后面是什么,有可能就像"仝"這個字,上下分開,一年級小學(xué)生都會,可是這樣拼在一起,就不一定了,具體是什么字自己去查哈,這里告訴這條語句的作用是把cat/dev/null得到的內(nèi)容保存到messages中,先混個臉熟吧下一句你該樂了,該學(xué)了一招嘛但是這里我還是決定多花點時間說說這里的這個/dev/null,因為也許你還不知道為什么要保存到messages和wtmp中,而且cat的為什么是/dev/null在Linux操作系統(tǒng)中/dev/null和/dev/zero是兩個相似卻又很特殊的文件,特別是在shell腳本開發(fā)和系統(tǒng)運維過程中會經(jīng)常用這兩個文件,因此作為Linux系統(tǒng)工程師,你必須了解這兩個文件的區(qū)別和用法。一、/dev/null的用法:我們可以把/dev/null文件看作"黑洞",它非常等價于一個只寫文件,所有寫入/dev/null文件的內(nèi)容都會丟失,而從/dev/null文件中也讀取不到任何內(nèi)容。然而,也正因為這些特點,在shell腳本開發(fā)和命令行維護(hù)時,/dev/null文件就可大展身手,顯得非常的有用。1.禁止標(biāo)準(zhǔn)輸出例如:cat查看$filename文件,其回顯信息將為空[html]viewplaincopy#

cat

$filename

>

/dev/null

2.禁止標(biāo)準(zhǔn)錯誤例如:rm刪除文件時,若$badname文件不存在,那么如下的方式則會過濾回顯的錯誤信息[html]viewplaincopy#

rm

$badname

2>

/dev/null

3.禁止標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤的輸例如:cat查看$filename文件[html]viewplaincopy#

cat

$filename

2>/dev/null

>/dev/null

#如果"$filename"不存在,將不會有任何錯誤信息提示.#如果"$filename"存在,文件的內(nèi)容不會打印到標(biāo)準(zhǔn)輸出.#因此上面的代碼根本不會輸出任何信息.4.清除日志文件內(nèi)容例如:[html]viewplaincopy#

cat

/dev/null

>

/var/log/wtmp

#

cat

/dev/null

>

/var/log/messages

#:>/var/log/messages有同樣的效果,但不會產(chǎn)生新的進(jìn)程.〔因為:是內(nèi)建的這里你還要知道怎么就會清空了wtmp和messages這兩個文件呢?因為你cat/dev/null的結(jié)果為空啊,然后你又把空內(nèi)容保存到這兩個文件中,不就相當(dāng)于清空嘛5./dev/null的特殊用法,程序打印的日志將不再記錄,避免系統(tǒng)空間被不需要的日志所占用稍微高級一點的,例如:[html]viewplaincopy#

ln

-s

/dev/null

~/.netscape/cookies

將該cookie的日志文件鏈接到/dev/null,那么往該文件中寫入的內(nèi)容都將被拋棄二、/dev/zero的用法:/dev/zero和/dev/null一樣,也是一個偽文件,但/dev/zero實際上能產(chǎn)生連續(xù)不斷的null的流〔二進(jìn)制的零流,而不是ASCII型的,寫入/dev/zero的輸出會丟失不見,而從/dev/zero讀出一連串的null也比較困難,雖然這也能通過dd或一個十六進(jìn)制編輯器來做到,/dev/zero主要的用處是用來創(chuàng)建一個指定長度用于初始化的空文件,它通常都是配合dd命令一起使用的。1.用/dev/zero創(chuàng)建一個指定大小的臨時文件例如:結(jié)合dd命令可創(chuàng)建一個大小為1024*1000bit的文件/swap,當(dāng)然這個文件的大小可通過bs和count參數(shù)去調(diào)整[html]viewplaincopy#

dd

if=/dev/zero

of=/swap

bs=1024count=10002.通過/dev/zero將零填充到一個指定大小的文件,以使用某些特殊需求例如:把RAM設(shè)備的內(nèi)容用零填充,從而實現(xiàn)格式化RAM的目的[html]viewplaincopy#

dd

if=/dev/zero

of=$DEVICE

count=$SIZE

bs=$BLOCKSIZE

綜上所述,/dev/null和/dev/zero文件的區(qū)別和用法如下:/dev/null文件是空設(shè)備,也稱為位桶〔bitbucket,它主要是用于"被寫入",任何寫入它的輸出都會被拋棄。如果不想讓消息以標(biāo)準(zhǔn)輸出顯示或?qū)懭胛募?那么可以將消息重定向到/dev/null。因此凡是向/dev/null輸入的任何數(shù)據(jù),它通吃,并且不會撐著!/dev/zero文件主要是用作一個標(biāo)準(zhǔn)的"0"輸入設(shè)備,它可無窮盡地提供0,可以使用/dev/zero來初始化文件。清除:一個改良的清除腳本[html]viewplaincopy#!/bin/bash

LOG_DIR=/var/log

cd

$LOG_DIR

cat

/dev/null

>

messages

cat

/dev/null

>

wtmp

echo

"Logs

cleaned

up."

exit

#這個命令是一種正確并且合適的退出腳本的方法,算是比較標(biāo)準(zhǔn)的"helloworld"現(xiàn)在,讓我們看一下一個真正意義的腳本,而且我們可以走得更遠(yuǎn),這里只是將上面的單條命令匯總到一個bash文件中一并處理,俗稱"批處理"清除:一個增強(qiáng)的和廣義的刪除logfile的腳本[html]viewplaincopy#!/bin/bash

LOG_DIR=/var/log

ROOT_UID=0LINES=10E_XCD=66E_NOTROOT=67if

[

"$UID"

-ne

"$ROOT_UID"

]

then

echo

"Must

be

root

ro

run

this

script!"

exit

$E_NOTROOT

fi

#if

[

-n

"$1"

]

#then

#

lines=$1

#else

#

lines=$LINES

#fi

E_WORNGPARAM=65case

"$1"

in

""

>

lines=10;;

*[!0-9]*>

echo

"Usage:

wong

param!";exit

$E_WRONGPARAM;;

*

>

lines=$1;;

esac

#cd

$LOG_DIR

#if

[

"$PWD"

!=

"$LOG_DIR"

]

#then

#

echo

"Can't

change

to

$LOG_DIR"

#

exit

$E_XCD

#fi

cd

/var/log

||

{

echo

"Can't

change

to

necessary

directory."

>&2

exit

$E_XCD

}

tail

-$lines

messages

>

mesg.tmp

mv

mesg.tmp

messages

cat

/dev/null

>

messages

cat

/dev/null

>

wtmp

echo

"Logs

cleaned

up!"

exit

0

因為你可能希望將系統(tǒng)log全部消滅,這個版本留下了log消息最后的部分.你將不斷地找到新的方法來完善這個腳本,并提高效率.要注意,在每個腳本的開頭都使用sha-bang<#!>,這意味著告訴你的系統(tǒng)這個文件的執(zhí)行需要指定一個解釋器.#!實際上是一個2字節(jié)的魔法數(shù)字,這是指定一個文件類型的特殊標(biāo)記,換句話說,在這種情況下,指的就是一個可執(zhí)行的腳本<鍵入manmagic來獲得關(guān)于這個迷人話題的更多詳細(xì)信息>.在sha-bang之后接著是一個路徑名.這個路徑名就是解釋腳本中命令的解釋程序所在的路徑,可能是一個shell,也可能是一個程序語言,也可能是一個工具包中的命令程序.這個解釋程序從頭開始解釋并且執(zhí)行腳本中的命令<從sha-bang行下邊的一行開始>,忽略注釋.這里強(qiáng)調(diào)文件中的第一個sha-bang才有意義,并且必須在開頭,之后如果再次出現(xiàn)sha-bang不會解析為sha-bang,舉例說明如下:[html]viewplaincopy#!/bin/bash

echo

"Part

1

of

script."

a=1#!/bin/bash

#這將不會啟動一個新腳本.

echo

"Part

2

of

script."

echo

$a

每一個腳本頭的行都指定了一個不同的命令解釋器,如果是/bin/sh,那么就是默認(rèn)shell<在Linux系統(tǒng)上默認(rèn)就是bash>,否則的話就是其他解釋器.舉例說明如下:[html]viewplaincopy#!/bin/rm

#

自刪除腳本.作為rm命令,直接刪除自己,more命令顯示自己的內(nèi)容

#

當(dāng)你運行這個腳本時,

基本上什么都不會發(fā)生.

.

.

當(dāng)然這個文件消失不見了.

WHATEVER=65echo

"This

line

will

never

print

<betcha!>."

exit

$WHATEVER

#

不要緊,

腳本是不會在這退出的.

使用#!/bin/sh,因為大多數(shù)的商業(yè)UNIX系統(tǒng)上都是以Bourneshell作為默認(rèn)shell,這樣可以使腳本移植到non-Linux的機(jī)器上,雖然這將會犧牲Bash一些獨特的特征.但是腳本將與POSIX的sh標(biāo)準(zhǔn)相一致.注意"sha-bang"后邊給出的路徑名必須是正確的,否則將會出現(xiàn)一個錯誤消息--通常是"Commandnotfound"--這將是你運行這個腳本時所得到的唯一結(jié)果.當(dāng)然#!也可以被忽略,不過這樣你的腳本文件就只能是一些命令的集合,不能夠使用shell內(nèi)建的指令了.上邊第二個例子必須以#!開頭,是因為分配變量了,lines=50,這就使用了一個shell特有的用法.再次提醒你#!/bin/sh將會調(diào)用默認(rèn)的shell解釋器,在Linux機(jī)器上默認(rèn)是/bin/bash.這里對上面的腳本做以下分析:1.定義變量2.檢查腳本是否獲取到root權(quán)限,采用兩種方式,一種便于理解,一種更加專業(yè)一點的做法3.檢查輸入?yún)?shù),采用兩種方式,一種便于理解,一種更加專業(yè)一點的做法4.檢查是否進(jìn)入/var/log目錄,采用兩種方式,一種便于理解,一種更加專業(yè)一點的做法5.執(zhí)行cleanup動作最后鼓勵你使用模塊化的方式來編寫腳本.平時也要多注意收集一些比較有代表性的"模版"代碼,這些零碎的代碼可能用在你將來編寫的腳本中.最后你就能生成一個很好的可擴(kuò)展的例程庫.以下邊這個腳本為例,這個腳本用來測試腳本被調(diào)用的參數(shù)數(shù)量是否正確.大多數(shù)情況下,你需要編寫一個腳本來執(zhí)行一個特定的任務(wù),在本章中第一個腳本就是一個這樣的例子,然后你會修改它來完成一個不同的,但比較相似的任務(wù).使用變量來代替寫死<"硬編碼<hard-wired>">的常量,就是一個很好的習(xí)慣,將重復(fù)的代碼放到一個函數(shù)中,也是一種好習(xí)慣.高級Bash腳本編程指南<2>:Shell特殊字符成于堅持,敗于止步#注釋1.表示注釋2.在引號中間和\#等表示#本身3.echo${PATH#*:}#參數(shù)替換,不是一個注釋4.echo$<<2#101011>>#數(shù)制轉(zhuǎn)換,不是一個注釋;分隔1.命令分隔,在一行中寫多個命令echo"aa";echo"bb"2.在條件中的if和then如果放在同一行,也用;分隔;;case條件的結(jié)束1.命令分隔,在一行中寫多個命令echo"aa";echo"bb"2.在條件中的if和then如果放在同一行,也用;分隔[html]viewplaincopyecho

hello;

echo

there

if

[

-x

"$filename"

];

then

#

注意:

"if"和"then"需要分隔.

echo

"File

$filename

exists.";

cp

$filename

$filename.bak

else

echo

"File

$filename

not

found.";

touch

$filename

fi;

echo

"File

test

complete."

.命令相當(dāng)于1.命令:source2.文件名的前綴,隱藏文件3.目錄:.當(dāng)前目錄,..父目錄4.正則表達(dá)式:匹配任意單個字符首先,先舉例說明一下"."作為source使用的實例[html]viewplaincopy#!/bin/bash

.

data-file

#

加載一個數(shù)據(jù)文件.

#

與"source

data-file"效果相同,

但是更具可移植性.

#

文件"data-file"必須存在于當(dāng)前工作目錄,

因為這個文件是使用'basename'來引用的.

echo

"variable1

=

$variable1"

echo

"variable3

=

$variable3"

let

"sum

=

$variable2

+

$variable4"

echo

"sum

=

$sum"

exit

0

上面是編寫的data_file腳本,通過.data-file引入,相當(dāng)于c語言中的includedata-file,我們看看data-file的內(nèi)容[html]viewplaincopy#

這是需要被腳本加載的數(shù)據(jù)文件.

#

這種文件可以包含變量,

函數(shù),

等等.

#

在腳本中可以通過'source'或者'.'命令來加載.

#

讓我們初始化一些變量.

variable1=22variable2=474variable3=5variable4=97message1="Hello,

how

are

you?"message2="Enough

for

now.

Goodbye."接下來我們看看腳本的執(zhí)行結(jié)果:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

chmod

777

include_file

root@ubuntu:~/resource/study/shell_study#

ls

clear_log

data-file

include_file

show_self

root@ubuntu:~/resource/study/shell_study#

./include_file

variable1

=

22variable3

=

5sum

=

571上面的結(jié)果已經(jīng)很有力的說明了我們想要的結(jié)論.作為隱藏文件時,建立隱藏文件的方法:touch.data-file.作為匹配字符說明如下:ab.可以表示ab+任意字符,處理換行,并且必須是一個字符ab.不能表示ab""部分引用支持通配符擴(kuò)展"STRING"將會阻止<解釋>STRING中大部分特殊的字符'‘全引用,不進(jìn)行通配符擴(kuò)展'STRING'將會阻止STRING中所有特殊字符的解釋.這是一種比使用"更強(qiáng)烈的形式\轉(zhuǎn)義\X將會"轉(zhuǎn)義"字符X.這等價于"X",也等價于'X'.\通常用來轉(zhuǎn)義"和',這樣雙引號和單引號就不會被解釋成特殊含義了./目錄分隔符分隔文件名不同的部分<比如/home/bozo/projects/Makefile>.也可以用來作為除法算術(shù)操作符.,多個命令都被執(zhí)行,但返回最后一個逗號操作符鏈接了一系列的算術(shù)操作.雖然里邊所有的內(nèi)容都被運行了,但只有最后一項被返回.[html]viewplaincopylet

"t2

=

<<a

=

9,

15

/

3>>"

#

Set

"a

=

9"

and

"t2

=

15

/

3"

逗號之前會運算,但是只有最后一項被返回`后置引用`command`結(jié)構(gòu)可以將命令的輸出賦值到一個變量中去.[html]viewplaincopycd

$LOG_DIR

if

[

`pwd`

!=

"$LOG_DIR"

]

then

echo

"Can't

change

to

$LOG_DIR"

exit

$E_XCD

fi

這里例子是最有力的的說明,在上一章中只不過沒有到這個方法,這里pwd命令會返回當(dāng)前路徑,然后與LOG_DIR進(jìn)行比較,同樣你可以定義一個變量保存pwd返回的內(nèi)容,比如:path=`pwd`:操作符1.空操作,等價于"NOP"<noop,一個什么也不干的命令>.

2.死循環(huán):while:,可以被認(rèn)為與shell的內(nèi)建命令,與true作用相同.[html]viewplaincopywhile

:

do

operation-1

operation-2

...

operation-n

done

#與下邊相同:[html]viewplaincopy#

while

true

#

do

#

...

#

done

3.在if/then中表示什么都不做,引出分支[html]viewplaincopyif

condition

then

:

#

什么都不做,引出分支.

else

take-some-action

fi

4.設(shè)置默認(rèn)參數(shù):${username=`whoami`}[html]viewplaincopy:

${username=`whoami`}

#

${username=`whoami`}

如果沒有開頭的":"的話,

將會給出一個錯誤,

除非"username"是一個命令或者內(nèi)建命令

5.變量替換:${HOSTNAME?}${USER?}${MAIL?}[html]viewplaincopy:

${HOSTNAME?}

${USER?}

${MAIL?}

#

如果一個或多個必要的環(huán)境變量沒被設(shè)置的話,

就打印錯誤信息.

6.在和><重定向操作符>結(jié)合使用時,把一個文件截斷到0長度,沒有修改它的權(quán)限;如果文件在之前并不存在,那么就創(chuàng)建它.如:

:>data.xxx#文件"data.xxx"現(xiàn)在被清空了.與cat/dev/null>data.xxx的作用相同然而,這不會產(chǎn)生一個新的進(jìn)程,因為":"是一個內(nèi)建命令.7.可能用來作為注釋行,雖然我們不推薦這么做.使用#來注釋的話,將關(guān)閉剩余行的錯誤檢查,所以可以在注釋行中寫任何東西.然而,使用:的話將不會這樣.:Thisisacommentthatgeneratesanerror,<if[$x-eq3]>.8.":"還用來在/etc/passwd和$PATH變量中做分隔符.[html]viewplaincopybash$

echo

$PATH

/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/games

*匹配0個或多個字符;數(shù)學(xué)乘法;**冪運算[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

ls

clear_log

data-file

include_file

show_self

root@ubuntu:~/resource/study/shell_study#

echo

*

clear_log

data-file

include_file

show_self

?匹配任意一個字符;但在<<a>b?a:b>>表示c語言中的三目運算<<t=a<45?7:11>>#C語言風(fēng)格的三元操作.$字符1.取變量的值echo$PATH[html]viewplaincopyvar1=5var2=23skidooecho

$var1

#

5

echo

$var2

#

23skidoo

2.正則表達(dá)式中表示行的結(jié)尾在正則表達(dá)式中,"$"表示行結(jié)束符,先分析一下下面的例子吧[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

echo

slfjalj$fdjgl

slfjalj

3.${}參數(shù)替換${PAHT}[html]viewplaincopy#!/bin/bash

#

param-sub.sh

#

一個變量是否被聲明或設(shè)置,

#+

將會影響這個變量是否使用默認(rèn)值,

#+

即使這個變量值為空<null>.

username0=

echo

"username0

has

been

declared,

but

is

set

to

null."

echo

"username0

=

${username0-`whoami`}"這里定義了username0且初始化是null,所以這里不會有輸出,這里的"-"相當(dāng)于"="

#

不會有輸出.

echo

echo

username1

has

not

been

declared.

echo

"username1

=

${username1-`whoami`}"這里username1在上面沒有定義并初始化為null,所以會顯示

#

將會輸出默認(rèn)值.

username2=

echo

"username2

has

been

declared,

but

is

set

to

null."

echo

"username2

=

${username2:-`whoami`}"這里上面初始化了username2并初始化為null,但是這里有個":"

#

^

#

會輸出,

因為:-會比-多一個條件測試.

#

可以與上邊的例子比較一下.

#

再來一個:

variable=

#

變量已經(jīng)被聲明,

但是設(shè)為空值.

echo

"${variable-0}"

#

<沒有輸出>

echo

"${variable:-1}"

#

1

#

^

unset

variable

echo

"${variable-2}"

#

2

echo

"${variable:-3}"

#

3

exit

0

我們也看看他的執(zhí)行結(jié)果:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

chmod

777

para_sub

root@ubuntu:~/resource/study/shell_study#

ls

clear_log

data-file

include_file

para_sub

show_self

root@ubuntu:~/resource/study/shell_study#

./para_sub

username0

has

been

declared,

but

is

set

to

null.

username0

=

username1

has

not

been

declared.

username1

=

rootusername2

has

been

declared,

but

is

set

to

null.

username2

=

root

^

1

2

3

4.$*所有參數(shù)5.$#參數(shù)個數(shù)6.$$進(jìn)程的ID7.$?進(jìn)程的返回狀態(tài)<>字符1.命令組,在一個子Shell中運行<a=3;echo$a>其中定義的變量在后面不可用在括號中的變量,由于是在子shell中,所以對于腳本剩下的部分是不可用的.父進(jìn)程,也就是腳本本身,將不能夠讀取在子進(jìn)程中創(chuàng)建的變量,也就是在子shell中創(chuàng)建的變量.[html]viewplaincopya=123<

a=321;

>

echo

"a

=

$a"

#

a

=

123#

在圓括號中a變量,

更像是一個局部變量.

2.數(shù)組初始化:array=<a,b,c>{}大括號擴(kuò)展[html]viewplaincopycat

{file1,file2,file3}

>

combined_file

#

把file1,

file2,

file3連接在一起,

并且重定向到combined_file中.

cp

file22.{txt,backup}

#

拷貝"file22.txt"到"file22.b

{}代碼塊,即一個匿名函數(shù),但其中定義的變量在后面依然可用[html]viewplaincopy#!/bin/bash

#

從/etc/fstab中讀行.

File=/etc/fstab

{

read

line1

read

line2

read

line3

}

<

$File

echo

"First

line

in

$File

is:"

echo

"$line1"

echo

echo

"Second

line

in

$File

is:"

echo

"$line2"

echo

echo

"third

line

in

$File

is:"

echo

"$line3"

exit

0

執(zhí)行結(jié)果:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

./test1

First

line

in

/etc/fstab

is:

#

/etc/fstab:

static

file

system

information.

Second

line

in

/etc/fstab

is:

#

third

line

in

/etc/fstab

is:

#

Use

'blkid

-o

value

-s

UUID'

to

print

the

universally

unique

identifier

接下來看一個例子:[html]viewplaincopy#!/bin/bash

{

echo

"Just

for

a

test:"

echo

`pwd`

echo

"Test

end"

}

>

"test-context"

#

把代碼塊中的所有輸出都重定向到文件中.

echo

"Results

of

rpm

test

in

test-context"

exit

0

看看運行結(jié)果:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

chmod

777

test2

root@ubuntu:~/resource/study/shell_study#

./test2

Results

of

rpm

test

in

test-context

root@ubuntu:~/resource/study/shell_study#

ls

clear_log

include_file

show_self

test2

data-file

para_sub

test1

test-context

root@ubuntu:~/resource/study/shell_study#

cat

test-context

Just

for

a

test:

/root/resource/study/shell_study

Test

end

{}\;用在find的-exec中$find-name*.txt-execcat{}\;[]字符1.測試[-z$1]2.數(shù)組元素a[1]='test'3.[[]]表示測試使用[[...]]條件判斷結(jié)構(gòu),而不是[...],能夠防止腳本中的許多邏輯錯誤.比如,&&,||,<,和>操作符能夠正常存在于[[]]條件判斷結(jié)構(gòu)中,但是如果出現(xiàn)在[]結(jié)構(gòu)中的話,會報錯.4.<<>>數(shù)學(xué)運算5.在正則表達(dá)式中表示范圍[a-z]<<<>重定向和進(jìn)程替換ls-al>a.txtscriptname>filename重定向scriptname的輸出到文件filename中.如果filename存在的話,那么將會被覆蓋.command&>filename重定向command的stdout和stderr到filename中.command>&2重定向command的stdout到stderr中.scriptname>>filename把scriptname的輸出追加到文件filename中.如果filename不存在的話,將會被創(chuàng)建.[i]<>filename打開文件filename用來讀寫,并且分配文件描述符i給這個文件.如果filename不存在,這個文件將會被創(chuàng)建.><還用在ASCII比較if[["$veg1"<"$veg2"]]\<,\>正則表達(dá)式中的單詞邊界.如:bash$grep'\<the\>'textfile|管道分析前邊命令的輸出,并將輸出作為后邊命令的輸入.這是一種產(chǎn)生命令鏈的好方法.echols-l|sh#傳遞"echols-l"的輸出到shell中,與一個簡單的"ls-l"結(jié)果相同.cat*.lst|sort|uniq#合并和排序所有的".lst"文件,然后刪除所有重復(fù)的行.

管道是進(jìn)程間通訊的一個典型辦法,將一個進(jìn)程的stdout放到另一個進(jìn)程的stdin中.標(biāo)準(zhǔn)的方法是將一個一般命令的輸出,比如cat或者echo,傳遞到一個"過濾命令"<在這個過濾命令中將處理輸入>中,然后得到結(jié)果.cat$filename1$filename2|grep$search_word當(dāng)然輸出的命令也可以傳遞到腳本中.[html]viewplaincopy#!/bin/bash

#

uppercase.sh

:

修改輸入,

全部轉(zhuǎn)換為大寫.

tr

'a-z'

'A-Z'

#

字符范圍必須被""引用起來來阻止產(chǎn)生單字符的文件名.

exit

0

現(xiàn)在讓我們輸送ls-l的輸出到一個腳本中.[html]viewplaincopybash$

ls

-l

|

./uppercase.sh

-RW-RW-R--

1

BOZO

BOZO

109

APR

7

19:49

1.TXT

-RW-RW-R--

1

BOZO

BOZO

109

APR

14

16:48

2.TXT

-RW-R--R--

1

BOZO

BOZO

725

APR

20

20:56

DATA-FILE

管道中的每個進(jìn)程的stdout比須被下一個進(jìn)程作為stdin來讀入.否則,數(shù)據(jù)流會阻塞,并且管道將產(chǎn)生一些非預(yù)期的行為.catfile1file2|ls-l|sort#從"catfile1file2"中的輸出并沒出現(xiàn).作為子進(jìn)程的運行的管道,不能夠改變腳本的變量.variable="initial_value"echo"new_value"|readvariableecho"variable=$variable"#variable=initial_value如果管道中的某個命令產(chǎn)生了一個異常,并中途失敗,那么這個管道將過早的終止.這種行為被叫做brokenpipe,并且這種狀態(tài)下將發(fā)送一個SIGPIPE信號.>|強(qiáng)制重定向<即使設(shè)置了noclobber選項--就是-C選項>.這將強(qiáng)制的覆蓋一個現(xiàn)存文件.||邏輯或操作;用在兩個命令之間的時候,表示在前一個命令結(jié)束時,若返回值為false,繼續(xù)執(zhí)行下一個命令&&邏輯與;用在兩個命令之間的時候,表示在前一個命令結(jié)束時,若返回值為true,繼續(xù)執(zhí)行下一個命令&后臺運行看一個例子[html]viewplaincopy#!/bin/bash

#

background-loop.sh

for

i

in

1

2

3

4

5

6

7

8

9

10

#

第一個循環(huán).

do

echo

echo

-n

"$i

"

done

&

#

在后臺運行這個循環(huán).

#

在第2個循環(huán)之后,

將在某些時候執(zhí)行.

echo

#

這個'echo'某些時候?qū)⒉粫@示.

for

i

in

11

12

13

14

15

16

17

18

19

20

#

第二個循環(huán).

do

echo

-n

"$i

"

done

echo

#

這個'echo'某些時候?qū)⒉粫@示.

exit

0

看一下結(jié)果:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

./for_test

11

12

13

14

15

16

17

18

19

20

root@ubuntu:~/resource/study/shell_study#

1

2

3

4

5

6

7

8

9

10

-在所有的命令內(nèi)如果想使用選項參數(shù)的話,前邊都要加上"-".1.參數(shù)選項2.減號3.重定向stdin和stdout:cd/source/directory&&tarcf-.>|<cd/dest/directory&&tarxpvf->4.先前的工作目錄cd-5.注:使用-開頭的文件名和變量名可能會出現(xiàn)一些問題+一個命令或者過濾器的選項標(biāo)記.~home目錄~+當(dāng)前工作目錄~-先前工作目錄^正則表達(dá)式中表示行首其中命令的很多細(xì)節(jié)并沒有研究的很徹底,好多好碎,以后見到用到具體的命令再具體分析吧高級Bash腳本編程指南<3>:變量和參數(shù)的介紹成于堅持,敗于止步變量替換變量的名字就是變量保存值的地方.引用變量的值就叫做變量替換."$"這個符號就好像是一種標(biāo)志讓我們仔細(xì)的區(qū)別變量的名字和變量的值.如果variable是一個變量的名字,那么$variable就是引用這變量的值,即這邊變量所包含的數(shù)據(jù).[html]viewplaincopyroot@ubuntu:~#

variable=12root@ubuntu:~#

echo

variable

variable

root@ubuntu:~#

echo

$variable

12

當(dāng)變量沒有$前綴的時候,那么變量可能存在如下幾種情況.1.變量被聲明或被賦值,2.變量被unset,3.變量被exporte,4.變量處在一種特殊的情況,變量代表一種信號變量賦值可以使用=<比如var1=27>,也可以在read命令中或者循環(huán)頭進(jìn)行賦值<forvar2in123>.被一對雙引號<"">括起來的變量替換是不會被阻止的.所以雙引號被稱為部分引用,有時候又被稱為"弱引用".但是如果使用單引號的話<''>,那么變量替換就會被禁止了,變量名只會被解釋成字面的意思,不會發(fā)生變量替換.所以單引號被稱為全引用,有時候也被稱為"強(qiáng)引用".注意$variable事實上只是${variable}的簡寫形式.在某些上下文中$variable可能會引起錯誤,這時候你就需要用${variable}了下面以一個例子做說明[html]viewplaincopy#!/bin/bash

#

變量賦值和替換

a=375

#這里沒有$說明是聲明并且賦值了

hello=$a

#$a表示使用變量a的值,把這個值賦值給hello這個變量

#

#

強(qiáng)烈注意,

在賦值的的時候,

等號前后一定不要有空格.

#

如果出現(xiàn)空格會怎么樣?

#

"VARIABLE

=value"

#

腳本將嘗試運行一個"VARIABLE"的命令,

帶著一個"=value"參數(shù).

#

"VARIABLE=

value"

#

腳本將嘗試運行一個"value"的命令,

并且?guī)е粋€被賦值成""的環(huán)境變量"VARIABLE".

#

echo

hello

#沒有$這里打印hello變量的名字

echo

$hello

#打印hello變量的值

echo

${hello}

#同樣是打印hello變量的值

echo

"$hello"

echo

"${hello}"

hello="A

B

C

D"

#重新賦值

echo

$hello

#

A

B

C

D

引用一個變量將保留其中的空白,

當(dāng)然,

如果是變量替換就不會保留了.

echo

"$hello"

#

A

B

C

D

echo

'$hello'

hello=

echo

"\$hello

<null

value>

=

$hello"

V3=23var1=21var2=22var3=$V3

echo

"var1=$var1

var2=$var2

var3=$var3"

numbers="one

two

three"other_numbers="1

2

3"echo

"numbers

=

$numbers"

echo

"other_numbers

=

$other_numbers"

mixed_bag=2\

\

Whatever

echo

"$mixed_bag"

echo

"uninitialized_variable

=

$uninitialized_variable"

uninitialized_variable=

echo

"uninitialized_variable

=

$uninitialized_variable"

uninitialized_variable=23unset

uninitialized_variable

echo

"uninitialized_variable

=

$uninitialized_variable"

exit

0

看看這個腳本的執(zhí)行結(jié)果:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

./value-test

hello

375

375

375

375

A

B

C

D

A

B

C

D

$hello

$hello

<null

value>

=

var1=21var2=22var3=23numbers

=

one

two

three

other_numbers

=

1

2

3

2

Whatever

uninitialized_variable

=

uninitialized_variable

=

uninitialized_variable

=

一個未初始化的變量將會是"null"值-就是未賦值<但并不是代表值是0!>.在給變量賦值之前就使用這個變量通常都會引起問題.但是在執(zhí)行算術(shù)操作的時候,仍然有可能使用未初始化過的變量[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

echo

"$data"

root@ubuntu:~/resource/study/shell_study#

let

"data

+=5"

root@ubuntu:~/resource/study/shell_study#

echo

"$data"

5

結(jié)論:一個未初始化的變量是沒有值的,但是在做算術(shù)操作的時候,這個未初始化的變量看起來值為0.這是一個未文檔化<并且可能不具可移植性>的行為.

賦值操作<前后都不能有空白>因為=和-eq都可以用做條件測試操作,所以不要與這里的賦值操作相混淆.注意:=既可以用做條件測試操作,也可以用于賦值操作,這需要視具體的上下文而定.簡單的賦值操作舉例:[html]viewplaincopy#!/bin/bash

#

賦值

a=879echo

"The

value

of

\"a\"

is

$a."

#

使用'let'賦值

let

a=16+5

echo

"The

value

of

\"a\"

is

now

$a."

#

在'for'循環(huán)中<事實上,

這是一種偽賦值>:

echo

-n

"Values

of

\"a\"

in

the

loop

are:

"

#這里加上-n表示忽略string最后的換行操作,否則會換行

for

a

in

7

8

9

11

do

echo

-n

"$a

"

done

echo

#

使用'read'命令進(jìn)行賦值<這也是一種賦值的類型>:

echo

-n

"Enter

\"a\":

"

read

a

#讀取輸入的值

echo

"The

value

of

\"a\"

is

now

$a."

exit

0

實驗結(jié)果:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

./value-test1

The

value

of

"a"

is

879.

The

value

of

"a"

is

now

21.

Values

of

"a"

in

the

loop

are:

7

8

9

11

Enter

"a":

121212

The

value

of

"a"

is

now

121212.

再看一個稍微復(fù)雜一點的例子:[html]viewplaincopy#!/bin/bash

a=23

#

簡單的賦值

echo

$a

b=$a

echo

$b

#

現(xiàn)在讓我們來點小變化<命令替換>.

a=`echo

Hello!`

#

把'echo'命令的結(jié)果傳給變量'a'

echo

$a

a=`ls

-l`

#

把'ls

-l'的結(jié)果賦值給'a'

echo

$a

#

然而,

如果沒有引號的話將會刪除ls結(jié)果中多余的tab和換行符.

echo

echo

"$a"

#

如果加上引號的話,

那么就會保留ls結(jié)果中的空白符.

exit

0

看一看實驗結(jié)果:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

chmod

777

value-test2

root@ubuntu:~/resource/study/shell_study#

./value-test2

23

23

Hello!

total

48

-rwxrwxrwx

1

root

root

663

2013-04-22

03:34

clear_log

-rw-r--r--

1

root

root

354

2013-04-22

03:15

data-file

-rwxrwxrwx

1

root

root

404

2013-04-22

05:05

for_test

-rwxrwxrwx

1

root

root

345

2013-04-22

03:16

include_file

-rwxrwxrwx

1

root

root

831

2013-04-22

04:08

para_sub

-rwxrwxrwx

1

root

root

253

2013-04-22

00:35

show_self

-rwxrwxrwx

1

root

root

256

2013-04-22

04:41

test1

-rwxrwxrwx

1

root

root

204

2013-04-22

04:50

test2

-rw-r--r--

1

root

root

59

2013-04-22

04:50

test-context

-rwxrwxrwx

1

root

root

1221

2013-04-23

22:33

value-test

-rwxrwxrwx

1

root

root

415

2013-04-23

22:51

value-test1

-rwxrwxrwx

1

root

root

439

2013-04-23

22:57

value-test2

total

48

-rwxrwxrwx

1

root

root

663

2013-04-22

03:34

clear_log

-rw-r--r--

1

root

root

354

2013-04-22

03:15

data-file

-rwxrwxrwx

1

root

root

404

2013-04-22

05:05

for_test

-rwxrwxrwx

1

root

root

345

2013-04-22

03:16

include_file

-rwxrwxrwx

1

root

root

831

2013-04-22

04:08

para_sub

-rwxrwxrwx

1

root

root

253

2013-04-22

00:35

show_self

-rwxrwxrwx

1

root

root

256

2013-04-22

04:41

test1

-rwxrwxrwx

1

root

root

204

2013-04-22

04:50

test2

-rw-r--r--

1

root

root

59

2013-04-22

04:50

test-context

-rwxrwxrwx

1

root

root

1221

2013-04-23

22:33

value-test

-rwxrwxrwx

1

root

root

415

2013-04-23

22:51

value-test1

-rwxrwxrwx

1

root

root

439

2013-04-23

22:57

value-test2

Bash變量是不區(qū)分類型的不像其他程序語言一樣,Bash并不對變量區(qū)分"類型".本質(zhì)上,Bash變量都是字符串.但是依賴于具體的上下文,Bash也允許比較操作和整數(shù)操作.其中的關(guān)鍵因素就是,變量中的值是否只有數(shù)字.下面看一下一個實例;[html]viewplaincopy#!/bin/bash

a=2334

#

整型.

let

"a

+=

1"

echo

"a

=

$a

"

#

a

=

2335b=${a/23/BB}

#

將"23"替換成"BB".

echo

"b

=

$b"

#

b

=

BB35declare

-i

b

#

即使使用declare命令也不會對此有任何幫助.

echo

"b

=

$b"

#

b

=

BB35let

"b

+=

1"

#

BB35

+

1

=

echo

"b

=

$b"

#

b

=

1c=BB34echo

"c

=

$c"

#

c

=

BB34d=${c/BB/23}

#

將"BB"替換成"23".

#

這使得變量$d變?yōu)橐粋€整形.

echo

"d

=

$d"

#

d

=

2334let

"d

+=

1"

#

2334

+

1

=

echo

"d

=

$d"

#

d

=

2335#

null變量會如何呢?

e=""echo

"e

=

$e"

#

e

=

let

"e

+=

1"

#

算術(shù)操作允許一個null變量?

echo

"e

=

$e"

#

e

=

1#

如果沒有聲明變量會怎樣?

echo

"f

=

$f"

#

f

=

let

"f

+=

1"

#

算術(shù)操作能通過么?

echo

"f

=

$f"

#

f

=

1#

所以說Bash中的變量都是不區(qū)分類型的.

exit

0

看一看他是執(zhí)行結(jié)果:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

./int-char

a

=

2335b

=

BB35b

=

BB35b

=

1c

=

BB34d

=

2334d

=

2335e

=

e

=

1

f

=

f

=

1

不區(qū)分變量的類型既是幸運的事情也是悲慘的事情.它允許你在編寫腳本的時候更加的靈活<但是也足夠把你搞暈!>,并且可以讓你能夠更容易的編寫代碼.然而,這也很容易產(chǎn)生錯誤,并且讓你養(yǎng)成糟糕的編程習(xí)慣.這樣的話,程序員就承擔(dān)了區(qū)分腳本中變量類型的責(zé)任.Bash是不會為你區(qū)分變量類型的.特殊的變量類型局部變量這種變量只有在代碼塊或者函數(shù)中<參見函數(shù)中的局部變量>才可見.環(huán)境變量這種變量將影響用戶接口和shell的行為在通常情況下,每個進(jìn)程都有自己的"環(huán)境",這個環(huán)境是由一組變量組成的,這些變量中存有進(jìn)程可能需要引用的信息.在這種情況下,shell與一個一般的進(jìn)程沒什么區(qū)別.每次當(dāng)一個shell啟動時,它都將創(chuàng)建適合于自己環(huán)境變量的shell變量.更新或者添加一個新的環(huán)境變量的話,這個shell都會立刻更新它自己的環(huán)境<譯者注:換句話說,更改或增加的變量會立即生效>,并且所有的shell子進(jìn)程<即這個shell所執(zhí)行的命令>都會繼承這個環(huán)境.<譯者注:準(zhǔn)確地說,應(yīng)該是后繼生成的子進(jìn)程才會繼承Shell的新環(huán)境變量,已經(jīng)運行的子進(jìn)程并不會得到它的新環(huán)境變量>.分配給環(huán)境變量的空間是有限的.創(chuàng)建太多環(huán)境變量,或者給一個環(huán)境變量分配太多的空間都會引起錯誤.如果一個腳本要設(shè)置一個環(huán)境變量,那么需要將這些變量"export"出來,也就是需要通知到腳本本地的環(huán)境.這是export命令的功能.

一個腳本只能夠export變量到這個腳本所產(chǎn)生的子進(jìn)程,也就是說只能夠?qū)@個腳本所產(chǎn)生的命令和進(jìn)程起作用.如果腳本是從命令行中調(diào)用的,那么這個腳本所export的變量是不能影響命令行環(huán)境的.也就是說,子進(jìn)程是不能夠export變量來影響產(chǎn)生自己的父進(jìn)程的環(huán)境的.位置參數(shù)從命令行傳遞到腳本的參數(shù):$0,$1,$2,$3...

$0就是腳本文件自身的名字,$1是第一個參數(shù),$2是第二個參數(shù),$3是第三個參數(shù),然后是第四個.

$9之后的位置參數(shù)就必須用大括號括起來了,比如,${10},${11},${12}.

兩個比較特殊的變量$*和$@表示所有的位置參數(shù).還是看一個實例吧[html]viewplaincopy#!/bin/bash

#

作為用例,

調(diào)用這個腳本至少需要10個參數(shù),

比如:

#

./scriptname

1

2

3

4

5

6

7

8

9

10

MINPARAMS=10echo

"The

name

of

this

script

is

\"$0\"."

echo

"The

name

of

this

script

is

\"`basename

$0`\"."

if

[

-n

"$1"

]

#

測試變量被引用.

then

echo

"Parameter

#1

is

$1"

#

需要引用才能夠轉(zhuǎn)義"#"

fi

if

[

-n

"$2"

]

then

echo

"Parameter

#2

is

$2"

fi

if

[

-n

"$3"

]

then

echo

"Parameter

#3

is

$3"

fi

if

[

-n

"${10}"

]

#

大于$9的參數(shù)必須用{}括起來.

then

echo

"Parameter

#10

is

${10}"

fi

echo

""

echo

"All

the

command-line

parameters

are:

"$*""

if

[

$#

-lt

"$MINPARAMS"

]

then

echo

"This

script

needs

at

least

$MINPARAMS

command-line

arguments!"

fi

exit

0

看看實驗結(jié)果:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

./args

1

2

3

The

name

of

this

script

is

"./args".

The

name

of

this

script

is

"args".

Parameter

#1

is

1

Parameter

#2

is

2

Parameter

#3

is

3

All

the

command-line

parameters

are:

1

2

3

This

script

needs

at

least

10

command-line

arguments!

root@ubuntu:~/resource/study/shell_study#

./args

1

2

3

4

5

6

7

8

9

10

11

The

name

of

this

script

is

"./args".

The

name

of

this

script

is

"args".

Parameter

#1

is

1

Parameter

#2

is

2

Parameter

#3

is

3

Parameter

#10

is

10

All

the

command-line

parameters

are:

1

2

3

4

5

6

7

8

9

10

11

{}標(biāo)記法提供了一種提取從命令行傳遞到腳本的最后一個位置參數(shù)的簡單辦法一些腳本可能會依賴于使用不同的調(diào)用名字,來表現(xiàn)出不同的行為.如果想要達(dá)到這種目的,一般都需要在腳本中檢查$0.因為腳本只能夠有一個真正的文件名,如果要產(chǎn)生多個名字,必須使用符號鏈接.

看一下shift命令的使用實例:[html]viewplaincopy#!/bin/bash

#

使用'shift'來逐步存取所有的位置參數(shù).

給腳本命個名,

比如shft,然后給腳本傳遞一些位置參數(shù),

比如:

./shft

a

b

c

def

23

skidoo

until

[

-z

"$1"

]

#

直到所有的位置參數(shù)都被存取完...

do

echo

-n

"$1

"

shift

done

echo

exit

0

查看實驗結(jié)果:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

./shift

d

df

lsjf

sldjf

d

df

lsjf

sldjf

先到這里了,O<∩_∩>O~高級Bash腳本編程指南<4>:shell中的引用成于堅持,敗于止步引用的字面意思就是將字符串用雙引號括起來.它的作用就是保護(hù)字符串中的特殊字符不被shell或者shell腳本重新解釋,或者擴(kuò)展.<我們這里所說的"特殊"指的是一些字符在shell中具有的特殊意義,而不是字符的字面意思,比如通配符--*.>在日常的演講和寫作中,當(dāng)我們"引用"一個短語的時候,這意味著這個短語被區(qū)分以示它有特別的含義.但是在Bash腳本中,當(dāng)我們引用一個字符串的時候,我們區(qū)分這個字符串是為了保護(hù)它的字面含義.某些程序和工具能夠重新解釋或者擴(kuò)展被引用的特殊字符.引用的一個重要作用就是保護(hù)命令行參數(shù)不被shell解釋,但是還是能夠讓正在調(diào)用的程序來擴(kuò)展它.[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study/txt-folder#

grep

[Tt]his

*.txt

file1.txt:this

is

the

first

file

file2.txt:This

the

second

file

root@ubuntu:~/resource/study/shell_study/txt-folder#

grep

'[Tt]his'

*.txt

file1.txt:this

is

the

first

file

file2.txt:This

the

second

file

這在我的bash下都是可以實現(xiàn)的引用還可以改掉echo's不換行的"毛病".[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study/txt-folder#

echo

$<ls

-l>

total

8

-rw-r--r--

1

root

root

23

2013-04-23

23:34

file1.txt

-rw-r--r--

1

root

root

21

2013-04-23

23:34

file2.txt

root@ubuntu:~/resource/study/shell_study/txt-folder#

echo

'$<ls

-l>'

$<ls

-l>

root@ubuntu:~/resource/study/shell_study/txt-folder#

echo

"$<ls

-l>"

total

8

-rw-r--r--

1

root

root

23

2013-04-23

23:34

file1.txt

-rw-r--r--

1

root

root

21

2013-04-23

23:34

file2.txt

在一個雙引號中通過直接使用變量名的方法來引用變量,一般情況下都是沒問題的.這么做將阻止所有在引號中的特殊字符被重新解釋--包括變量名,但是$,`<后置引用>,和\<轉(zhuǎn)義符>除外.

保留$作為特殊字符的意義是為了能夠在雙引號中也能夠正常的引用變量<"$variable">,也就是說,這個變量將被它的值所取代使用雙引號還能夠阻止單詞分割<wordsplitting>.如果一個參數(shù)被雙引號擴(kuò)起來的話,那么這個參數(shù)將認(rèn)為是一個單元,即使這個參數(shù)包含有空白,那里面的單詞也不會被分隔開.[html]viewplaincopy#!/bin/bash

var="'<]\\{}\$\""

echo

$var

#

'<]\{}$"

echo

"$var"

#

'<]\{}$"

和上一句沒什么區(qū)別.Doesn't

make

a

difference.

echo

IFS='\'echo

$var

#

'<]

{}$"

\

字符被空白符替換了,

為什么?

echo

"$var"

#

'<]\{}$"

exit

0

我們看看上面這個腳本的執(zhí)行結(jié)果:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

./echo-strange

'<]\{}$"

'<]\{}$"

'<]

{}$"

'<]\{}$"

針對IFS的用法以后再研究吧當(dāng)在命令行中使用時,如果在雙引號中包含"!"的話,那么會產(chǎn)生一個錯誤<譯者注:比如,echo"hello!">.這是因為感嘆號被解釋成歷史命令了.但是如果在腳本中,就不會存在這個問題,因為在腳本中Bash歷史機(jī)制是被禁用的.在雙引號中使用"\"也可能會出現(xiàn)一些不一致的行為[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

echo

"hello!"

bash:

!":

event

not

found

root@ubuntu:~/resource/study/shell_study#

echo

hello!

hello!

root@ubuntu:~/resource/study/shell_study#

echo

hello\!

hello!

root@ubuntu:~/resource/study/shell_study#

echo

"hello\!"

hello\!

root@ubuntu:~/resource/study/shell_study#

echo

ni\thao

nithao

root@ubuntu:~/resource/study/shell_study#

echo

"ni\thao"

ni\thao

root@ubuntu:~/resource/study/shell_study#

echo

-e

ni\thao

nithao

root@ubuntu:~/resource/study/shell_study#

echo

-e

"ni\thao"

ni

hao

單引號<''>操作與雙引號基本一樣,但是不允許引用變量,因為$的特殊意義被關(guān)閉了.在單引號中,任何特殊字符都按照字面的意思進(jìn)行解釋,除了'.所以說單引號<"全引用">是一種比雙引號<"部分引用">更嚴(yán)格的引用方法.因為即使是轉(zhuǎn)義符<\>在單引號中也是按照字面意思解釋的,所以如果想在一對單引號中顯示一個單引號是不行的下面這個例子:[html]viewplaincopyroot@ubuntu:~/resource/study/shell_study#

echo

"I'm

a

good

person"

I'm

a

good

person

root@ubuntu:~/resource/study/shell_study#

echo

'I'm

a

good

person'

>

^C

root@ubuntu:~/resource/study/shell_study#

echo

'I'\''m

a

good

person'

I'm

a

good

person

root@ubuntu:~/resource/study/shell_study#

echo

'I'"'"'m

a

good

person'

I'm

a

good

person

轉(zhuǎn)義是一種引用單個字符的方法.一個前面放上轉(zhuǎn)義符<\>的字符就是告訴shell這個字符按照字面的意思進(jìn)行解釋,換句話說,就是這個字符失去了它的特殊含義.在某些特定的命令和工具中,比如echo和sed,轉(zhuǎn)義符往往會起到相反效果-它反倒可能會引發(fā)出這個字符的特殊含義.特定的轉(zhuǎn)義符的特殊的含義echo和sed命令中使用\n表示新的一\r表示回車\t表示水平制表符\v表示垂直制表符\b表示后退符\a表示"alert"<蜂鳴或者閃爍>\0xx轉(zhuǎn)換為八進(jìn)制的ASCII碼,等價于0xx[html]viewplaincopy#!/bin/bash

echo

"\v\v\v\v"

#

逐字的打印\v\v\v\v.

#

使用-e選項的'echo'命令來打印轉(zhuǎn)義符.

echo

"==============="

echo

-e

"\v\v\v\v"

#

打印4個垂直制表符.

echo

"==============="

echo

-e

"\042"

#

打印"

<引號,

8進(jìn)制的ASCII

碼就是42>.

echo

"==============="

#

如果使用$'\X'結(jié)構(gòu),那-e選項就不必要了.

echo

$'\n

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論