Shell腳本的超詳細(xì)講解(推薦!)
一、Shell腳本基礎(chǔ)概念
1.1 什么是shell?
shell英文翻譯過來是外殼的意思,作為計(jì)算機(jī)語言來理解可以認(rèn)為它是操作系統(tǒng)的外殼。我們可以通過shell命令來操作和控制操作系統(tǒng),比如Linux中的shell命令就包括ls
、cd
、pwd
等等。
shell是站在內(nèi)核的基礎(chǔ)上編寫的一個應(yīng)用程序,它連接了用戶和Linux內(nèi)核,從而讓用戶能夠更加便捷、高效、安全的使用linux內(nèi)核,這其實(shí)就是shell的本質(zhì)。
使用專業(yè)術(shù)語的說法來解釋,Shell其實(shí)是一個命令解釋器,它通過接受用戶輸入的Shell命令來啟動、暫停、停止程序的運(yùn)行或?qū)τ?jì)算機(jī)進(jìn)行控制。
1.2 什么是shell腳本
shell腳本就是由Shell命令組成的執(zhí)行文件,將一些命令整合到一個文件中,進(jìn)行處理業(yè)務(wù)邏輯,腳本不用編譯即可運(yùn)行。它通過解釋器解釋運(yùn)行,所以速度相對來說比較慢。
1.3 shell腳本的意義
我們在1.2中也解釋道shell腳本其實(shí)就是shell命令組成的文件,shell腳本可以記錄命令執(zhí)行的過程和執(zhí)行邏輯,以便以后重復(fù)執(zhí)行,還可以批量、定時處理主機(jī),方便管理員進(jìn)行設(shè)置或者管理。
二、創(chuàng)建一個簡單的Shell腳本
2.1 創(chuàng)建一個shell腳本文件
在創(chuàng)建shell腳本時,我們默認(rèn)新建一個以.sh
/.script
結(jié)尾的文件,主要是為了讓程序員更加快捷的辨認(rèn)出該文件是一個shell腳本文件。
我們創(chuàng)建一個test.sh
的shell腳本文件,其中具體內(nèi)容為下:
#!/bin/bash echo hello
- " # ”開頭的就是注釋,單行注釋
- <<EOF … EOF 或 :<<! … ! :多行注釋
- #!/bin/bash : 主要用于指定解釋器
- Linux中提供的shell解釋器有:
- /bin/sh
- /bin/bash
- /usr/bin/sh
- /usr/bin/bash
2.2 運(yùn)行一個Shell腳本
我們根據(jù)腳本文件是否具有可執(zhí)行權(quán)限,將運(yùn)行一個shell腳本的方法分為兩大類。
2.2.1 腳本文件無執(zhí)行權(quán)限
這種情況下我們有三種方式來運(yùn)行腳本:
手動在環(huán)境中開啟指定解釋器:sh test.sh
直接在當(dāng)前環(huán)境中運(yùn)行的shell中運(yùn)行腳本:. test.sh
直接在當(dāng)前環(huán)境中運(yùn)行的shell中運(yùn)行腳本:source test.sh
2.2.2 腳本文件有執(zhí)行權(quán)限
在這一部分由于我們假設(shè)腳本文件有可執(zhí)行器權(quán)限,所以我們使用chmod +x test.sh
為我們的test.sh
文件增加了可執(zhí)行權(quán)限。
我們知道當(dāng)一個文件具有可執(zhí)行權(quán)限時我們可以使用該文件的路徑名直接運(yùn)行該文件,有兩種方式可以運(yùn)行腳本:
1.絕對路徑名運(yùn)行腳本文件
絕對路徑就是從根目錄下開始記錄文件路徑名,是文件在計(jì)算機(jī)上真正存在的路徑。(如果不知道你的文件路徑名,可以在當(dāng)前位置的shell中使用pwd
查詢當(dāng)前所在位置)
2../相對路徑名的格式運(yùn)行腳本文件
相對路徑是指以當(dāng)前的文件作為起點(diǎn),相較于當(dāng)前目錄的位置而被指向并且加以引用的文件資源。
比如我們知道test.sh
文件的絕對路徑為/home/westos/Desktop/textcpp/test.sh
,那么當(dāng)我們在testcpp文件夾中時,test.sh
文件的相對路徑為test.sh
。
又因?yàn)?code>.代表當(dāng)前所在位置,故而為其實(shí)./test.sh
其實(shí)就是該文件的絕對路徑,只是表示的方式不同。
三、基本語法
3.1 變量
變量名其實(shí)就是一片內(nèi)存區(qū)域的地址或者可以說是尋址符號,有了變量我們就可以使用一串固定的字符來表示不固定的目標(biāo)。
3.1.1 變量類型
在shell中會同時存在三種類型變量。
- 局部變量:局部變量在腳本或命令中定義,僅在當(dāng)前shell實(shí)例中有效,其他shell啟動的程序不能訪問局部變量。
- 環(huán)境變量:所有的程序,包括shell啟動的程序,都能訪問環(huán)境變量,有些程序需要環(huán)境變量來保證其正常運(yùn)行。必要的時候shell腳本也可以定義環(huán)境變量。
- shell變量:shell變量是由shell程序設(shè)置的特殊變量。shell變量中有一部分是環(huán)境變量,有一部分是局部變量,這些變量保證了shell的正常運(yùn)行
3.1.2 變量操作
- 創(chuàng)建普通變量:name=“test”,組要注意的是等號兩邊不能有空格。
- 創(chuàng)建局部變量:local name=“test”,使用local修飾的變量在函數(shù)體外無法訪問,只能在函數(shù)體中使用。
- 創(chuàng)建只讀變量:name=“only_read” -> readonly name,這種變量不可以被修改。
- 使用變量:echo $name或者echo ${name}
- 刪除變量:unset name,刪除之后的變量無法被訪問,需要注意無法刪除只讀變量。
3.1.3 字符串變量
3.1.3.1 字符串變量的創(chuàng)建
- 使用單引號創(chuàng)建:var='test'。
這種方式創(chuàng)建的變量只能原樣輸出,變量無效,我們可以借用c中的“字符串常量”的定義理解這種特性。除此以外,單引號中不能出現(xiàn)單獨(dú)的單引號,轉(zhuǎn)義也是不可以的。 - 使用雙引號創(chuàng)建:var="my name is ${name}",這種方式創(chuàng)建的字符串變量有效,也可以出現(xiàn)轉(zhuǎn)義符。
3.1.3.2 拼接字符串
- 字面量拼接
str01="1""2"或者str01="1"'2',這樣就將1和2兩個字符拼接在了一起。需要注意的是兩個串之間不可以有空格。 - 變量拼接
str03=${part01}${part02}或str04=${part01}"end"或str05="${part01} ${part02}"這三種方式都可以拼接字符串變量。 - 命令拼接
str02= date“end”,這里的date是一個shell命令,需要使用引用,具體如下:
str02=`date`"end"
3.1.3.3 獲取字符串長度
1.使用wc -L
命令
wc -L
可以獲取到當(dāng)前行的長度,因此對于單獨(dú)行的字符串可以用這個簡單的方法獲取,另外wc -l
則是獲取當(dāng)前字符串內(nèi)容的行數(shù)。
echo "abc" |wc -L
2.使用expr length
可以獲取string的長度
expr length ${<!--{C}%3C!%2D%2D%20%2D%2D%3E-->str}
3.awk獲取域的個數(shù)
但是如果大于10個字符的長度時是否存在問題需要后面確認(rèn)
echo "abc" |awk -F "" '{print NF}'
4.通過awk+length
的方式獲取字符串長度
echo “Alex”|awk '{print length($0)}'
5.通過echo ${#name}
的方式
name=Alex echo ${#name}
3.1.3.4 提取子字符串
1.如下方式:
代碼 | 意義 |
---|---|
${varible##*string} | 從左向右截取最后一個string后的字符串 |
${varible#*string} | 從左向右截取第一個string后的字符串 |
${varible%%string*} | 從右向左截取最后一個string后的字符串 |
${varible%string*} | 從右向左截取第一個string后的字符串 |
例,如下代碼:
$ MYVAR=foodforthought.jpg $ echo ${MYVAR##*fo}
運(yùn)行結(jié)果為rthought.jpg
2.使用${varible:n1:n2}
截取變量varible從n1到n2之間的字符串,可以根據(jù)特定字符偏移和長度,來選擇特定子字符串,如下代碼:
$ EXCLAIM=cowabunga $ echo ${EXCLAIM:0:3}
運(yùn)行結(jié)果最終顯示cow
。
3.1.4 數(shù)組
如果說變量是存儲單個變量的內(nèi)存空間,那么數(shù)組就是多個變量的集合,它存儲多個元素在一片連續(xù)的內(nèi)存空間中。在bash中,只支持一維數(shù)組,不支持多維數(shù)組。
3.1.3.1 數(shù)組定義與引用
定義一個數(shù)組方式如下:
數(shù)組名=(元素1 元素2 元素3 ... 元素n)
指定數(shù)組對應(yīng)下標(biāo)的元素進(jìn)行賦值:
數(shù)組名[下標(biāo)]=值
同時指定多個數(shù)組元素進(jìn)行賦值:
數(shù)組名=([下標(biāo)1]=值1 [下標(biāo)2]=值2 ... [下標(biāo)n]=值n)
引用數(shù)組對應(yīng)下標(biāo)的元素:
${數(shù)組名[下標(biāo)]}
3.1.3.2 遍歷數(shù)組元素
使用for
(或while
循環(huán))循環(huán)遍歷數(shù)組元素:
#!/bin/bash a=(1 2 3 4 5 6) for((i=0; i<10; i++)) do echo "a[$i]=${a[$i]}" done
除此以外我們還可以使用${a[*]}
或者${a[@]}
來遍歷數(shù)組元素,具體代碼如下:
#!/bin/bash a=(1 2 3 4 5 6) echo ${a[*]} echo ${a[@]}
3.1.3.3 獲取數(shù)組長度
我們可以使用#
來獲取數(shù)組長度,需要注意的是在shell腳本中我們越界訪問數(shù)組時是不會報錯的。
#!/bin/bash a=(1 2 3 4 5 6) echo ${a[*]} echo "a len: ${#a[*]}"
我們先使用其獲取數(shù)組中的元素后使用#
獲取元素個數(shù)即可。
3.1.3.4 合并數(shù)組
我們可以如下進(jìn)行拼接:
#!/bin/bash a=(1 2 3 4 5 6) b=("hello" "zhaixue.cc") c=(${a[*]} ${b[*]})
這樣我們就將兩個數(shù)組拼接起來了。
3.1.3.5 刪除數(shù)組元素
如果我們想要刪除某個數(shù)組元素,具體代碼如下:
#!/bin/bash a=(1 2 3 4 5 6) echo ${a[*]} echo "a len: ${#a[*]}" unset a[5] echo ${a[*]} echo "a len: ${#a[*]}"
執(zhí)行結(jié)果如下:
我們?nèi)绻獎h除整個數(shù)組,可以執(zhí)行unset a
,舉例代碼如下:
#!/bin/bash a=(1 2 3 4 5 6) echo ${a[*]} echo "a len: ${#a[*]}" unset a echo ${a[*]} echo "a len: ${#a[*]}"
3.1.5 變量傳參
相關(guān)的變量含義為:
變量 | 含義 |
---|---|
$0 | 代表執(zhí)行的文件名 |
$1 | 代表傳入的第1個參數(shù) |
$n | 代表傳入的第n個參數(shù) |
$# | 參數(shù)個數(shù) |
$* | 以一個單字符串顯示所有向腳本傳遞的參數(shù)。 |
$@ | 與$*相同,但是使用時加引號,并在引號中返回每個參數(shù) |
$$ | 腳本運(yùn)行的當(dāng)前進(jìn)程號 |
$! | 后臺運(yùn)行的最后一個進(jìn)程的ID |
$? | 顯示最后命令的退出狀態(tài)。0表示沒有錯誤,其他任何值表明有錯誤。 |
3.2 運(yùn)算符
原生的bash并不支持簡單的數(shù)學(xué)運(yùn)算,通常要通過其它命令來實(shí)現(xiàn)。
3.2.1 算數(shù)運(yùn)算符
以下表格中的a
和b
都是變量。
運(yùn)算 | shell中格式 |
---|---|
加法 | expr $a + $b |
減法 | expr $a - $b |
乘法 | expr $a \* $b |
除法 | expr $b / $a |
取余 | expr $b % $a |
賦值 | a=$b |
相等 | [ $a == $b ] |
不相等 | [ $a != $b ] |
需注意:
條件表法式需要放在方括號之間,并且要有空格。使用expr
進(jìn)行計(jì)算時需要使用反引號,為了讓讀者更容易理解,給出下列示例代碼。
#!/bin/bash a=10 b=20 val=`expr $a + $b` echo "a + b : $val"
3.2.2 關(guān)系運(yùn)算符
關(guān)系運(yùn)算符只支持?jǐn)?shù)字,不支持字符串,除非字符串的值是數(shù)字。
運(yùn)算 | shell中的實(shí)現(xiàn) | 主要符號 |
---|---|---|
檢測兩個數(shù)是否相等 | [ $a -eq $b ] | -eq |
檢測兩個數(shù)是否不相等 | [ $a -ne $b ] | -ne |
檢測左邊的數(shù)是否大于右邊的 | [ $a -gt $b ] | -gt |
檢測左邊的數(shù)是否小于右邊的 | [ $a -lt $b ] | -lt |
檢測左邊的數(shù)是否大于等于右邊的 | [ $a -ge $b ] | -ge |
檢測左邊的數(shù)是否小于等于右邊的 | [ $a -le $b ] | -le |
舉例代碼如下:
#!/bin/bash a=1 b=2 if [ $a != $b ] then echo "$a != $b : a 不等于 b" else echo "$a == $b: a 等于 b"
執(zhí)行結(jié)果如下:
3.2.3 布爾運(yùn)算符
具體如下:
運(yùn)算 | shell中的實(shí)現(xiàn) | 主要符號 |
---|---|---|
非運(yùn)算 | [ ! false ] | ! |
或運(yùn)算 | [ $a -lt 20 -o $b -gt 100 ] | -o |
與運(yùn)算 | [ $a -lt 20 -a $b -gt 100 ] | -a |
3.2.4 邏輯運(yùn)算符
具體如下:
運(yùn)算 | shell中的實(shí)現(xiàn) | 主要符號 |
---|---|---|
邏輯的 AND | [[ $a -lt 100 && $b -gt 100 ]] | && |
邏輯的 OR | [[ $a -lt 100 || $b -gt 100 ]] | || |
布爾運(yùn)算符和邏輯運(yùn)算符的區(qū)別:
語法上,邏輯運(yùn)算需要雙括弧,布爾運(yùn)算只需要單大括弧功能上,邏輯運(yùn)算具有特殊的短路功能,即是在AND運(yùn)算中第一個表達(dá)式為false時則不執(zhí)行第二個表達(dá)式,在OR運(yùn)算中第一個表達(dá)式為true時不執(zhí)行第二個表達(dá)式。
3.2.5 字符串運(yùn)算符
下表列出了常用的字符串運(yùn)算符:
運(yùn)算 | shell中的實(shí)現(xiàn) | 主要符號 |
---|---|---|
檢測兩個字符串是否相等 | [ $a = $b ] | = |
檢測兩個字符串是否不相等 | [ $a != $b ] | != |
檢測字符串長度是否為0 | [ -z $a ] | -z |
檢測字符串長度是否不為 0 | [ -n “$a” ] | -n |
檢測字符串是否為空 | [ $a ] | $ |
3.2.6 文件測試運(yùn)算符
主要用于檢測unix文件的各種屬性:
運(yùn)算 | shell中的實(shí)現(xiàn) | 主要符號 |
---|---|---|
檢測文件是否是塊設(shè)備文件 | [ -b $file ] | -b file |
檢測文件是否是字符設(shè)備文件 | [ -c $file ] | -c file |
檢測文件是否是目錄 | [ -d $file ] | -d file |
檢測文件是否是普通文件(既不是目錄,也不是設(shè)備文件) | [ -f $file ] 返回 true | -f file |
檢測文件是否設(shè)置了 SGID 位 | [ -g $file ] | -g file |
檢測文件是否設(shè)置了粘著位(Sticky Bit) | [ -k $file ] | -k file |
檢測文件是否是有名管道 | [ -p $file ] | -p file |
檢測文件是否設(shè)置了 SUID 位 | [ -u $file ] | -u file |
檢測文件是否可讀 | [ -r $file ] | -r file |
檢測文件是否可寫 | [ -w $file ] | -w file |
檢測文件是否可執(zhí)行 | [ -x $file ] | -x file |
檢測文件是否為空(文件大小是否大于0) | [ -s $file ] | -s file |
檢測文件(包括目錄)是否存在 | [ -e $file ] | -e file |
舉例如下:
#!/bin/bash file="/home/westos/Desktop/textcpp/test.sh" if [ -r $file ] then echo "文件可讀" else echo "文件不可讀" fi
執(zhí)行結(jié)果為:
3.2.7 運(yùn)算指令
1.(( ))
我們可以直接使用雙圓括弧計(jì)算其中的內(nèi)容,如((var=a+b)),該指令經(jīng)常在if/while等條件判斷中需要計(jì)算時使用。
2.let
在計(jì)算表達(dá)式的時候我們可以直接使用let,如let var=a+b。
3.expr
在前面的內(nèi)容中我們也提到了它,是非常常用的計(jì)算指令,使用時需要在外部增反引號
var=`expr a+b`
4.bc計(jì)算器
bc計(jì)算器支持shell中的小數(shù)進(jìn)行運(yùn)算,并且可以交互式或者非交互式的使用。基本使用方式為var=$(echo "(1.1+2.1)"|bc)
;
5.$[]
我們可以直接使用這種方式計(jì)算中括弧中的內(nèi)容,如echo $[1+2]
3.3 控制語句
和其他語句不同,shell的流傳呢個控制不可為空。接下來我們?yōu)榇蠹医榻Bsehll中常用的語法。
3.3.1 if語句結(jié)構(gòu)
3.3.1.1 if-fi
就類似于c中的if條件判斷,如下:
if condition then command1 command2 ... commandN fi
3.3.1.2 if-else-fi
代碼如下:
if condition then command1 else command2 fi
若condition成立則執(zhí)行command1,否則執(zhí)行command2。
3.3.1.3 if else-if else
代碼如下:
if condition1 then command1 elif condition2 then command2 else command3 fi
若condition1成立,執(zhí)行command1,若condition1不成立,condition2成立執(zhí)行command2,若兩個condition都不成立就執(zhí)行command3。
3.3.2 循環(huán)結(jié)構(gòu)
3.3.2.1 for循環(huán)
格式為:
for var in item1 item2 ... itemN do command1 command2 ... commandN done
以上也可以寫做一行,若變量var
在列表中,則for循環(huán)執(zhí)行一次所有命令。以以下代碼作為測試:
#!/bin/bash for loop in 1 2 3 4 5 do echo "The value is: $loop" done
執(zhí)行結(jié)果為:
3.3.2.2 while循環(huán)
格式如下:
while condition do command done
我們運(yùn)行如下代碼:
#!/bin/bash int=1 while(( $int<=5 )) do echo $int let "int++" done
執(zhí)行的最終結(jié)果為:
3.3.2.3 無限循環(huán)
我們可以以上兩種語句給出無限循環(huán)的實(shí)現(xiàn),首先看一下for循環(huán)如何實(shí)現(xiàn):
for (( ; ; ))
除此以外我們也可以使用while循環(huán)實(shí)現(xiàn)如下:
while : do command done
或者直接將while中的判斷語句置為真:
while true do command done
3.3.2.4 until循環(huán)
until 循環(huán)執(zhí)行一系列命令直至條件為 true 時停止。語法格式如下:
until condition do command done
3.3.2.5 跳出循環(huán)
在循環(huán)過程中,有時候需要在未達(dá)到循環(huán)結(jié)束條件時強(qiáng)制跳出循環(huán),Shell使用兩個命令來實(shí)現(xiàn)該功能:break
和continue
。
1.break跳出循環(huán)
當(dāng)我們需要跳出當(dāng)前循環(huán),或者終止死循環(huán)時,我們就可以使用break來跳出循環(huán)。接下來我們運(yùn)行如下代碼:
#!/bin/bash var=1 while(( $var < 5 )) do if(( $var>3 )) then echo "跳出循環(huán)" break fi echo "$var" var=`expr $var + 1` done
執(zhí)行結(jié)果為:
在該循環(huán)中var>3
時break,而是直接跳出循環(huán)。
2.continue跳出循環(huán)
continue命令與break命令類似,只有一點(diǎn)差別,它不會跳出所有循環(huán),僅僅跳出當(dāng)前循環(huán)。 接下來我們運(yùn)行如下代碼:
#!/bin/bash var=1 while(( $var < 5 )) do if(( $var>3 )) then echo "跳出循環(huán)" continue fi echo "$var" var=`expr $var + 1` done
執(zhí)行結(jié)果為:
使用continue跳出的循環(huán)只是當(dāng)前循環(huán),無法跳出整個循環(huán),由于在該代碼中我們每次執(zhí)行到continue就會跳出當(dāng)前循環(huán),無法執(zhí)行 var=expr $var + 1
,所以循環(huán)條件一直成立,就成了死循環(huán)。
3.3.3 case-esac多選擇語句
case ... esac
為多選擇語句,與其他語言中的switch ... case
語句類似,是一種多分支選擇結(jié)構(gòu),每個 case
分支用右圓括號開始,用兩個分號 ;;
表示 break,即執(zhí)行結(jié)束,跳出整個 case … esac 語句,esac
(就是 case 反過來)作為結(jié)束標(biāo)記。
case 要求取值后面必須為單詞 in,每一模式必須以右括號結(jié)束。取值可以為變量或常數(shù),匹配發(fā)現(xiàn)取值符合某一模式后,其間所有命令開始執(zhí)行直至 ;;。
若檢測匹配時無一匹配,使用*
捕獲該值,再執(zhí)行后續(xù)命令。
語法格式如下:
case 值 in 模式1) command1 command2 ... commandN ;; 模式2) command1 command2 ... commandN ;; *) command1 esac
3.3.3 select-in語句
select in是shell中獨(dú)有的一種循環(huán),非常適合終端的交互場景,它可以顯示出帶編號的菜單,用戶出入不同編號就可以選擇不同的菜單,并執(zhí)行不同的功能。
語法格式如下:
select var in seq do action done
我們執(zhí)行如下代碼:
#!/bin/bash echo "What is your favourite OS?" select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do break; done echo "You have selected $var"
執(zhí)行結(jié)果為:
四、函數(shù)
函數(shù)其實(shí)就是將一段代碼組合封裝在一起實(shí)現(xiàn)某個特定的功能或返回某個特定的值。我們在定義函數(shù)時需要先起一個函數(shù)名,在使用的時候直接調(diào)用函數(shù)名即可。
4.1 定義函數(shù)
shell中定義函數(shù)格式如下:
[ function ] funname [()] { action; [return int;] }
注意:
1.以上的[ function ]
也可以省略
2.當(dāng)函數(shù)沒有return時,默認(rèn)返回最后一個命令的運(yùn)行結(jié)果作為返回值。
4.2 函數(shù)參數(shù)
在shell中,調(diào)用函數(shù)時可以向其傳遞參數(shù)。在函數(shù)內(nèi)部直接通過$n
獲取參數(shù)的值。我們給出示例如下:
#!/bin/bash funWithParam(){ echo "第一個參數(shù)為 $1 !" echo "第十個參數(shù)為 ${10} !" } funWithParam 1 2 3 4 5 6 7 8 9 34 73
需要注意$10
不能返回第十個參數(shù),當(dāng)n>10
的時候,需要使用$(n)
來獲取參數(shù)。
4.3 函數(shù)作用域
Shell腳本中執(zhí)行函數(shù)時并不會開啟子進(jìn)程,默認(rèn)在函數(shù)外部或函數(shù)內(nèi)部定義和使用變量的效果相同。函數(shù)外部的變量在函數(shù)內(nèi)部可以直接調(diào)用,反之函數(shù)內(nèi)部的變量也可以在函數(shù)外部直接調(diào)用。但是這樣會導(dǎo)致變量混淆、數(shù)據(jù)可能被錯誤地修改等等問題,那么如何解決這些問題呢?
系統(tǒng)為我們提供了一個local語句,該語句可以使在函數(shù)內(nèi)部定義的變量僅在函數(shù)內(nèi)部有效。定義時直接在變量前加local
即可。
五、重定向
一個命令通常從一個叫標(biāo)準(zhǔn)輸入的地方讀取輸入,默認(rèn)情況下,這恰好是你的終端。同樣,一個命令通常將其輸出寫入到標(biāo)準(zhǔn)輸出,默認(rèn)情況下,這也是你的終端。
一般情況下,每個 Unix/Linux 命令運(yùn)行時都會打開三個文件:
- 標(biāo)準(zhǔn)輸入文件(stdin):stdin的文件描述符為0,Unix程序默認(rèn)從stdin讀取數(shù)據(jù)。
- 標(biāo)準(zhǔn)輸出文件(stdout):stdout 的文件描述符為1,Unix程序默認(rèn)向stdout輸出數(shù)據(jù)。
- 標(biāo)準(zhǔn)錯誤文件(stderr):stderr的文件描述符為2,Unix程序會向stderr流中寫入錯誤信息。
但有些時候我們可能需要將數(shù)據(jù)從其它文件讀入或讀出,這就需要我們重定向。
5.1 輸入重定向
我們可以讓命令從文件中獲取,這樣本來的命令需要從標(biāo)準(zhǔn)輸入stdin
中獲取,轉(zhuǎn)換為從我們的指定文件中獲取。這樣本來需要從鍵盤輸入的命令就會轉(zhuǎn)移到文件讀取內(nèi)容。語法如下:
command1 < file
5.2 輸出重定向
同輸入重定向很相似,輸出重定向也是將本來需要輸出標(biāo)準(zhǔn)輸出文件stdout
中轉(zhuǎn)化為我們的指定文件中。語法如下:
command1 > file
5.3 標(biāo)準(zhǔn)錯誤文件重定向
我們可以直接借助標(biāo)準(zhǔn)錯誤文件的文件描述符來重定向stderr
,語法如下:
$ command 2>file
擴(kuò)充一點(diǎn),如果我們想將stdout
標(biāo)準(zhǔn)輸出文件和stderr
標(biāo)準(zhǔn)錯誤文件合并重定向到一個指定文件中,語法如下:
$ command > file 2>&1
5.4 Here Document
Here Document 是 Shell 中的一種特殊的重定向方式,用來將輸入重定向到一個交互式 Shell 腳本或程序。它的作用是將兩個 delimiter 之間的內(nèi)容(document) 作為輸入傳遞給 command。基本語法如下:
command << delimiter documentdelimiter
注意:
結(jié)尾的delimiter 一定要頂格寫,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 縮進(jìn)。開始的delimiter前后的空格會被忽略掉。
5.5 /dev/null 文件
如果希望執(zhí)行某個命令,但又不希望在屏幕上顯示輸出結(jié)果,那么可以將輸出重定向到 /dev/null中,/dev/null 是一個特殊的文件,寫入到它的內(nèi)容都會被丟棄;如果嘗試從該文件讀取內(nèi)容,那么什么也讀不到。但是 /dev/null 文件非常有用,將命令的輸出重定向到它,會起到"禁止輸出"的效果。語法如下:
$ command > /dev/null
總結(jié)
到此這篇關(guān)于Shell腳本的超詳細(xì)講解的文章就介紹到這了,更多相關(guān)Shell腳本講解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Shell腳本實(shí)現(xiàn)監(jiān)測文件變化的示例詳解
這篇文章主要和大家分享一個Shell腳本,可以實(shí)現(xiàn)監(jiān)測文件變化功能。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-06-06Shell腳本實(shí)現(xiàn)的一個簡易Web服務(wù)器例子分享
這篇文章主要介紹了Shell腳本實(shí)現(xiàn)的一個簡易Web服務(wù)器例子分享,本文實(shí)現(xiàn)的Web服務(wù)器非常簡單實(shí)用,可以在你不想安裝nginx、apache等大型WEB服務(wù)器時使用,需要的朋友可以參考下2014-12-12shell腳本5種執(zhí)行方式及腳本不同的執(zhí)行方法和區(qū)別詳解
我們都知道bash?shell?腳本的方法有多種,下面這篇文章主要給大家介紹了關(guān)于shell腳本5種執(zhí)行方式及腳本不同的執(zhí)行方法和區(qū)別的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07使用Linux shell腳本實(shí)現(xiàn)FTP定時執(zhí)行批量下載指定文件
使用FTP定時批量下載指定文件的shell腳本,具體實(shí)例介紹如下所示,需要的朋友參考下吧2017-04-04Linux中的service命令與systemctl命令有何區(qū)別
在Linux中,service?和?systemctl?是兩個至關(guān)重要且極其相似的命令,它們?nèi)绱讼嗨?,以至于人們很容易想知道它們之間有何不同,是否可以互換使用,下面我們就來看看之前的區(qū)別到底有哪些吧2023-08-08