20170805bash學習

bash學習

參考

Linux bash總結(一) 基礎部分(適合初學者學習和非初學者參考)
Linux 入門公開課
C語言中文網(wǎng)-Shell教程
處理linux的echo命令不輸出轉義符號的問題
runoob-Shell 教程
Linux標準輸入/輸出和重定向
Linux 輸入輸出重定向, &>file, 2>&1, 1>&2 等
exec的重定向 - GitHub
linux shell 管道命令(pipe)使用及與shell重定向區(qū)別

數(shù)據(jù)類型

1.數(shù)值

2.字符串

字符串可以用單引號,也可以用雙引號,也可以不用引號。單雙引號的區(qū)別跟PHP類似

2.1單引號

單引號的特點:

  • 單引號里的任何字符都會原樣輸出,單引號字符串中的變量是無效的;
  • 單引號字串中不能出現(xiàn)單引號(對單引號使用轉義符后也不行
[chen@localhost tmp]$ echo 'hello$val'
hello$val

2.2雙引號

雙引號的優(yōu)點:

  • 雙引號里可以有變量
  • 雙引號里可以出現(xiàn)轉義字符
[chen@localhost tmp]$ echo "${val}hello\'"
1hello\'

字符串更多操作,見下面的 運算/2字符串運算

變量&數(shù)組

1.變量

1.1定義,使用

  • 變量的定義不加$
  • 不加$表示變量本身,可以val++,加$表示變量存儲的值val=$val+1
  • val=anything 等號兩側不能有空格
ubuntu@VM-10-194-ubuntu:/tmp$ VAR="some"
ubuntu@VM-10-194-ubuntu:/tmp$ NUM=123
# 注意:等號兩側不能有空格! 變量名稱全部用大寫是編程慣例
ubuntu@VM-10-194-ubuntu:/tmp$ echo VAR
VAR
ubuntu@VM-10-194-ubuntu:/tmp$ echo $VAR
some
# 調用變量要加 $
[chen@localhost tmp]$ $val=hello
-bash: 1=hello: command not found
#$val表示變量存儲的值,不能作為左值

1.2只讀變量

格式 readonly val

[chen@localhost tmp]$ val=hello
[chen@localhost tmp]$ readonly val
[chen@localhost tmp]$ val=1
-bash: val: readonly variable

1.3刪除變量

格式 unset val

1.4變量類型

運行shell時,會同時存在三種變量:

  • 局部變量 局部變量在腳本或命令中定義,僅在當前shell實例中有效,其他shell啟動的程序不能訪問局部變量。
  • 環(huán)境變量 所有的程序,包括shell啟動的程序,都能訪問環(huán)境變量,有些程序需要環(huán)境變量來保證其正常運行。必要的時候shell腳本也可以定義環(huán)境變量。
  • shell變量 shell變量是由shell程序設置的特殊變量。shell變量中有一部分是環(huán)境變量,有一部分是局部變量,這些變量保證了shell的正常運行

2.數(shù)組

2.1定義,使用

定義 數(shù)組名=(值1 值2 ... 值n) 或者 數(shù)組名[下標]=值
使用 ${數(shù)組名[下標]}

#創(chuàng)建 a=( )
ubuntu@VM-10-194-ubuntu:/tmp$ a=(1 2 3 f g)
ubuntu@VM-10-194-ubuntu:/tmp$ echo $a
1
#顯示所有元素或者echo ${a[*]}    {}表示內部是一個整體,也可以 ${val},傳入?yún)?shù)$10時也要${10}
ubuntu@VM-10-194-ubuntu:/tmp$ echo ${a[@]}
1 2 3 f g
#顯示數(shù)組元素,0代表第1個元素
ubuntu@VM-10-194-ubuntu:/tmp$ echo ${a[2]}   
3
ubuntu@VM-10-194-ubuntu:/tmp$ a["sth"]=TT  #這樣也行
ubuntu@VM-10-194-ubuntu:/tmp$ echo ${a[@]} 
TT 2 3 f g
#或者逐個創(chuàng)建
ubuntu@VM-10-194-ubuntu:/tmp$ a[6]=100
ubuntu@VM-10-194-ubuntu:/tmp$ echo ${a[@]}
TT 2 3 f g 100
#顯示數(shù)組元素刪除a[2]的值,并不刪除a[2]
ubuntu@VM-10-194-ubuntu:/tmp$ unset a[2]   
ubuntu@VM-10-194-ubuntu:/tmp$ echo ${a[2]}

ubuntu@VM-10-194-ubuntu:/tmp$ unset a   #刪除數(shù)組a所有元素
#${數(shù)組名[@或*]:起始位置:長度} 輸出數(shù)組的第1-3項
ubuntu@VM-10-194-ubuntu:/tmp$ echo ${a[@]:0:3}
#${數(shù)組名[@或*]/查找字符/替換字符   替換輸出,并不改變數(shù)組
ubuntu@VM-10-194-ubuntu:/tmp$ echo ${a[*]/1/6}

2.2獲取數(shù)組長度

# 取得數(shù)組元素的個數(shù)
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得數(shù)組單個元素的長度
lengthn=${#array_name[n]}

bash文件

1. 創(chuàng)建文件

ubuntu@VM-10-194-ubuntu:/tmp$ > test.sh
ubuntu@VM-10-194-ubuntu:/tmp$ touch test2.sh
ubuntu@VM-10-194-ubuntu:/tmp$ echo "something" >test3.sh
ubuntu@VM-10-194-ubuntu:/tmp$ cat test3.sh 
something

創(chuàng)建多行,使用了重定向的知識,重定向見本文后段

ubuntu@VM-10-194-ubuntu:/tmp$ cat >test4.sh<<EOF
> some
> shu wan zhi jie hui che
> zi dong tian jia >
> EOF
#EOF為任意字符串
ubuntu@VM-10-194-ubuntu:/tmp$ cat test4.sh 
some
shu wan zhi jie hui che
zi dong tian jia >

不過還是喜歡,vi file 直接輸入
2. 添加執(zhí)行權限

$ chmod +x test.sh 

3. 編寫腳本

#!/bin/bash
echo "hello bash"
exit 0

說明:
#!/bin/bash : 它是bash文件聲明語句,表示是以/bin/bash程序執(zhí)行該文件。它必須寫在文件的第一行!
echo "hello bash" : 表示在終端輸出“hello bash”
exit 0 : 表示返回0。在bash中,0表示執(zhí)行成功,其他表示失敗。

4. 執(zhí)行

ubuntu@VM-10-194-ubuntu:/tmp$ ./test.sh 
hello bash

注釋

  • 單行注釋 以“#”開頭的行就是注釋
  • 多行注釋 sh里沒有多行注釋,可以把這一段要注釋的代碼用一對花括號括起來,定義成一個函數(shù),沒有地方調用這個函數(shù),這塊代碼就不會執(zhí)行,達到了和注釋一樣的效果
zhushi()
{
zhushi注釋內容
echo zhushi
}
:||{
被注釋的多行內容
}

運算

1 數(shù)值運算

數(shù)值元算主要有4種實現(xiàn)方式:(())、let、expr、bc。
工作效率:
(()) == let > expr > bc

  • (())和let是bash內建命令,執(zhí)行效率高,支持i++;而expr和bc是系統(tǒng)命令,會消耗內存,執(zhí)行效率低。
  • 只有bc支持浮點運算

#!/bin/bash
#(())  要加個$再賦予變量
val=$((3*(5+2)))
echo $val

#let
let "val=3*(5+2)"
echo $val

#expr 又費勁  注意是`重音符  ``輸出命令結果,例如val=`ls`,val=`date`
#還得用空格隔開運算符和數(shù)字,不然顯示不對
val=`expr 3 \* \( 5 + 2 \)`
echo $val

#bc 是重音符`
val=`echo "3*(5+2)"|bc`
echo $val

使用$(())或let來進行整數(shù)計算,bc進行浮點數(shù)計算
$(( 3+3 ))
val=`echo "scale=3;1/3"|bc` 重音符
**i++ ((val++))或者 let val++

2 字符串運算

2.1字符串的使用


ubuntu@VM-10-194-ubuntu:/tmp$ str="hello world"
ubuntu@VM-10-194-ubuntu:/tmp$ echo ${str}
hello world
ubuntu@VM-10-194-ubuntu:/tmp$ echo ${strq:?ERR_MSG}
-bash: strq: ERR_MSG

2.2 字符串操作


ubuntu@VM-10-194-ubuntu:/tmp$ echo ${#str}
11
ubuntu@VM-10-194-ubuntu:/tmp$ echo ${str:3:6}
lo wor
ubuntu@VM-10-194-ubuntu:/tmp$ echo ${str%ld}
hello wor
#并不影響原字符串
ubuntu@VM-10-194-ubuntu:/tmp$ echo ${str}
hello world

流程控制(判斷循環(huán))

1 條件判斷

1.1 test

語法

test EXPRESSION

test是關鍵字,表示判斷;
EXPRESSION是被判斷的語句。

1.1 數(shù)值判斷

參數(shù) 說明
-eq 等于則為真
-ne 不等于則為真
-gt 大于則為真
-ge 大于等于則為真
-lt 小于則為真
-le 小于等于則為真
[chen@localhost tmp]$ test 12 -eq 2
[chen@localhost tmp]$ echo $?
1
# $?表示上一命令的執(zhí)行結果(在linux中bash中,true返回0,false返回1

1.2字符串測試

參數(shù) 說明
= 等于則為真
!= 不相等則為真
-z 字符串 字符串的長度為零則為真
-n 字符串 字符串的長度不為零則為真

[chen@localhost tmp]$ test "hello" != "yes"
[chen@localhost tmp]$ echo $?
0

1.3文件測試

linux文件:目錄、鏈接、設備、文本。。。

參數(shù) 說明
-e 文件名 如果文件存在則為真
-r 文件名 如果文件存在且可讀則為真
-w 文件名 如果文件存在且可寫則為真
-x 文件名 如果文件存在且可執(zhí)行則為真
-s 文件名 如果文件存在且至少有一個字符則為真即文件長度大于0、非空
-d 文件名 如果文件存在且為目錄則為真
-f 文件名 如果文件存在且為普通文件則為真
-L 文件名 如果文件存在且為符號連接
-c 文件名 如果文件存在且為字符型特殊文件則為真
-b 文件名 如果文件存在且為塊特殊文件則為真
-u 文件名 如果文件存在且有suid位設置

ubuntu@VM-10-194-ubuntu:/tmp$ test -f ./123.txt 
ubuntu@VM-10-194-ubuntu:/tmp$ echo $?
0

1.2 []條件判斷

語法

[ EXPRESSION ]

中括號的左右擴弧和EXPRESSION之間都必須有空格
空格空格
關于EXPRESSION的說明,參考如下:

ubuntu@VM-10-194-ubuntu:/tmp$ [ -f test2.sh ]
ubuntu@VM-10-194-ubuntu:/tmp$ echo $?
0
ubuntu@VM-10-194-ubuntu:/tmp$ [ -f test2.s11h ]
ubuntu@VM-10-194-ubuntu:/tmp$ echo $?
1

1.3 邏輯

基本格式(上表也有)
-a : 邏輯與,操作符兩邊均為真,結果為真,否則為假。
-o : 邏輯或,操作符兩邊一邊為真,結果為真,否則為假。
! : 邏輯否,條件為假,結果為真。
[ expre ] && [ expre2 ] 與
[ expre ] || [ expre2 ] 或

#判斷test2.sh是否可讀寫
[ -r test2.sh -a -w test2.sh ]

2 if [ ] ; then cmd; elif [ ] ; then cmd ; else cmd ; fi

if 或者 elif 后面必須有then,else直接跟命令,可以沒有,最后以fi結尾
在bash文件中,回車,不需要分號,單行if命令需要分號
[] 可為 test、[]判斷,計算式(( ))等,以下涉及判斷條件同理
例1

 if [ 1 -eq 2 ] 
> then echo 1==2
> elif [ 2 -eq 3 ]
> then 2==3
> elif [ 3 -eq 4 ]
> then echo 3==4
> else echo 1=1 
> fi
#或者
if [ 1 -eq 2 ] ; then echo 1==2; elif [ 2 -eq 3 ]; then 2==3; elif [ 3 -eq 4 ]; then echo 3==4; else echo 1==1; fi
1==1

例2

#!/bin/bash
# 提示用戶輸入一個值
echo -n "please input a number:"
# 保存用戶的輸入到num中
read NUM
if [ $NUM -le 5 ] ;
then echo "$NUM<5";
else echo "$NUM>5";
#分號可有可無
fi
exit 0

3 case

# 格式
case 值 in
模式1}
命令1
...
;;
模式2)
命令2
...
;;
esac

#!/bin/bash
echo -n "are you femail(Y/N)"
read val
case $val in
Y|y)
echo "yes"
;;    # 注意此處有兩個;
N|n)
echo "no"
;;
*)
echo "incorrect input"
;;
esac      # 注意esac結束
exit 0

4 for循環(huán)

for 變量名in列表  或者 for  ((i=1;i<7;i++)),**注意兩個括號**
do
命令1
命令2...
done

# 判斷當前目錄下的文件并輸出文件名
#!/bin/bash
#將ls結果保存到變量CUR,
CUR=`ls`    #注意這里是Tab鍵上面的`
# 大部分Unix shell以及編程語言如Perl、PHP以及Ruby等都以成對的重音符作指令替代,意思是以
某一個指令的輸出結果作為另一個指令的輸入項。例如上述指令
echo $CUR
for val in $CUR
do     #do不可少
if [ -f $val ] ;
then  echo "FILE: $val" ;
fi
done   #done 不可少
exit 0
#計算10以內數(shù)的和
#!/bin/bash
sum=0
for ((i=1;i<10;i++))
do
((sum=$sum+$i))
# (( ))表示數(shù)值計算
done
echo "sum=$sum"
exit 0

5 until

循環(huán)至少運行一次
當滿足條件時不再執(zhí)行直接結束

until 條件
do
命令1
...
done

例;輸出5以內的自然數(shù)

#!/bin/bash
val=0
until (($val==5))   #或者[ "$val" -eq "5" ] 
do
echo $val
((val++))
done
exit 0

6 while

滿足條件才進行循環(huán),最少不運行

while 命令
do
命令1
命令2
...
done

例;輸出5以內的自然數(shù)

#!/bin/bash
val=0
while ((val<5))
do
echo $val
((val=$val+1))
done
exit 0

7 break 與continue

break命令允許跳出循環(huán)-----結束
continue命令跳過這個循環(huán)步-----進入下個循環(huán)

例break輸出5內自然數(shù)

#!/bin/bash
val=0
while true
do
if (($val==5));
then break;
fi
echo $val
((val++))
done
exit 0

例:從0開始逐步遞增到10:當數(shù)值為5時,將數(shù)值遞增2;否則,輸出數(shù)值

#!/bin/bash
val=0
while (($val<=10))
do
if (($val==5))   #好像沒有;用<Enter>也是可以的
then ((val=$val+2))
continue
else
echo $val 
((val++))
fi
done
exit 0

函數(shù)

所有函數(shù)在使用前必須定義。這意味著必須將函數(shù)放在腳本開始部分,直至shell解釋器首次發(fā)現(xiàn)它時,才可以使用。調用函數(shù)僅使用其函數(shù)名即可

1 定義

基本格式

function 函數(shù)名()
{
...
return 返回值;
}
  • function可有可無。但建議保留,因為保留的話看起來更加直觀
  • return 返回值,如果不加,將以最后一條命令運行結果,作為返回值
#!/bin/bash
function foo()
{
echo "hello"
return 5;
}
foo
echo $?
#直接編寫foo函數(shù)文件,在終端中運行foo“返回值為0”,沒有echo結果

結果

[chen@localhost tmp]$ ./han
hello
5

2 傳遞參數(shù)

$n代表輸入的第n個參數(shù)

foo param1 param2 param3
#參數(shù)變量出入函數(shù)內部為@ 例
echo $@
#輸出結果為
param1 param2 param3
參數(shù) 說明
$? 顯示上一條命令的退出狀態(tài)。判斷退出true為0,flase為1,函數(shù)退出結果為返回值,例
[chen@localhost tmp]$ ((1+1))
[chen@localhost tmp]$ echo $?
0
$# 傳遞到腳本的參數(shù)個數(shù)
$n 表示傳入的第n個參數(shù)
$10 不能獲取第十個參數(shù),獲取第十個參數(shù)需要${10}。當n>=10時,需要使用${n}來獲取參數(shù)
$* 以一個單字符串顯示所有向腳本傳遞的參數(shù)。如"$*"用「"」括起來的情況、以"$1 $2 … $n"的形式輸出所有參數(shù)。
$@ 與$*相同,但是使用時加引號,并在引號中返回每個參數(shù)。如"$@"用「"」括起來的情況、以"$1" "$2" … "$n" 的形式輸出所有參數(shù)。
$- 顯示Shell使用的當前選項,與set命令功能相同。
$$ 腳本運行的當前進程ID號
$! 后臺運行的最后一個進程的ID號
$0 當前sehll名 [chen@localhost tmp]$ echo $0 結果為-bash

$* 和 $@ 的區(qū)別

  • $* 和 $@ 表示傳遞給函數(shù)或腳本的所有參數(shù),不被雙引號(" ")包含時,都以"$1" "$2" … "$n" 的形式輸出所有參數(shù)。
  • 但是當它們被雙引號(" ")包含時,"$*" 會將所有的參數(shù)作為一個整體,以"$1 $2 … $n"的形式輸出所有參數(shù);"$@" 會將各個參數(shù)分開,以"$1" "$2" … "$n" 的形式輸出所有參數(shù)。

#!/bin/bash
for val in "$*"
do echo $val
done
echo \"
for val in "$@"
do echo $val
done
exit 0
ubuntu@VM-10-194-ubuntu:/tmp$ ./can 1 2 3 4
1 2 3 4
"
1
2
3
4

內建命令

1 內建指令查看

基本格式
type cmd
格式說明
type是命令關鍵字,cmd表示查看的命令;若輸出builtin,則該命令是bash的內建命令。
例如:
ubuntu@VM-10-194-ubuntu:/tmp$ type echo
echo is a shell builtin
除此之外,用戶也可以通過man bash或者man builtins查看bash的全部內置命令

2 常用內建命令

(01)echo
命令:echo arg
功能:在屏幕上顯示出由arg指定的字串
(02)read
命令格式:read變量名表
功能:從標準輸入設備讀入一行,分解成若干字,賦值給bash程序內部定義的變量
(03)shift
命令:shift [N] (N為大于0的整數(shù);當N省略時,等價與于“shift 1”)
功能:所有的參數(shù)依次向左移動N個位置,并使用$#減少N,直到$#=0為止。
(04)alias
命令:alias name='value'
功能:別名。用name替換value,value要用單引號括住。
(05)export
命令:export變量名[=變量值]
功能:export可以把bash的變量向下帶入子bash(即子bash中可以使用父bash的變量),從而讓子進程繼承父進程中的環(huán)境變量。但子bash不能用export把它的變量向上帶入父bash。
(06)readonly
命令:readonly 變量名
功能:定義只讀變量。不帶任何參數(shù)的readonly命令將顯示出所有只讀變量。
(07)exec
命令:exec 命令參數(shù)
功能:當bash執(zhí)行到exec語句時,不會去創(chuàng)建新的子進程,而是轉去執(zhí)行指定的命令,當指定的命令執(zhí)行完時,該進程(也就是最初的bash)就終止了,所以bash程序中exec后面的語句將不再 
被執(zhí)行。
(08)"."(點)
命令:. bash程序文件名
功能:使bash讀入指定的bash程序文件并依次執(zhí)行文件中的所有語句。
(09)exit
命令:exit N
功能:退出Shell程序。在exit之后可有選擇地指定一個數(shù)位作為返回狀態(tài)。

echo

  • echo是Shell的一個內部指令,用于在屏幕上打印出指定的字符串。命令格式
echo "anything"
"可有可無
  • 1 顯示轉義字符 backslash escapes
    在echo命令的幫助中,寫到默認禁止反斜杠功能。如果需要開起反斜杠轉義功能,需要使用-e的參數(shù)。
轉義字符 含義
\\ 反斜杠
\a 警報,響鈴
\b 退格(刪除鍵)
\f 換頁(FF),將當前位置移到下頁開頭
\n 換行
\r 回車
\t 水平制表符(tab鍵)
\v 垂直制表符

#!/bin/bash
echo -e  "hello\c"
echo "hell\c"
echo  hell
exit 0

結果

hellohell\c
hell

可看到,需要 -e 才能啟用轉義字符功能
對于 " /需要// /" /$來輸出,不適用上述規(guī)則

  • 2 顯示變量
echo $val

當變量與其它字符相連時用{}隔開

echo ${val}-2-3 
  • 3 顯示結果重定向至文件(寫入另一個文件)
[chen@localhost tmp]$ echo rete >file
[chen@localhost tmp]$ cat file
rete
  • 4 原樣輸出字符串
    單引號
[chen@localhost tmp]$ echo '\$cal'
\$cal
  • 5 輸出命令結果
    重音符`
[chen@localhost tmp]$ echo `date`
Mon Aug 7 00:23:33 PDT 2017

雙引號可有可無,單引號主要用在原樣輸出中,重音符輸出命令

printf

printf 命令用于格式化輸出, 是echo命令的增強版。它是C語言printf()庫函數(shù)的一個有限的變形,并且在語法上有些不同。

注意:printf 由 POSIX 標準所定義,移植性要比 echo 好。

格式

printf  format-string  [arguments...]
  • format-string 為格式控制字符串
  • arguments 為參數(shù)列表
[chen@localhost tmp]$ printf "%d%s%c%f\n" 1 "abc" "def" "0.1"
1abcd0.100000

%d %s %c %f 格式替代符詳解:
d:data 數(shù)字 -- 對應位置參數(shù)必須是數(shù)字型,否則報錯!
s:str 字符串 -- 對應位置參數(shù)必須是字符串或者字符型,否則報錯!
c:char 字符 -- 對應位置參數(shù)必須是字符串或者字符型,否則報錯!
f:float 浮點 -- 對應位置參數(shù)必須是數(shù)字型,否則報錯!
如:上面第三個參數(shù)是 "def",%c 自動截取字符串的第一個字符作為結果輸出,若第四個參數(shù)無0.1則輸出0.000000

轉義字符 含義
\\ 反斜杠
\a 警報,響鈴
\b 退格(刪除鍵)
\f 換頁(FF),將當前位置移到下頁開頭
\n 換行
\r 回車
\t 水平制表符(tab鍵)
\v 垂直制表符
\c 抑制(不顯示)輸出結果中任何結尾的換行字符(只在%b格式指示符控制下的參數(shù)字符串中有效),而且,任何留在參數(shù)里的字符、任何接下來的參數(shù)以及任何留在格式字符串中的字符,都被忽略
\ddd 表示1到3位數(shù)八進制值的字符。僅在格式字符串中有效
\0ddd 表示1到3位的八進制值字符

指定輸出寬度
%-10s 指一個寬度為10個字符(-表示左對齊,沒有則表示右對齊)
默認轉義

轉義字符 含義
\\ 反斜杠
\a 警報,響鈴
\b 退格(刪除鍵)
\f 換頁(FF),將當前位置移到下頁開頭
\n 換行
\r 回車
\t 水平制表符(tab鍵)
\v 垂直制表符
\c 抑制(不顯示)輸出結果中任何結尾的換行字符(只在%b格式指示符控制下的參數(shù)字符串中有效),而且,任何留在參數(shù)里的字符、任何接下來的參數(shù)以及任何留在格式字符串中的字符,都被忽略
\ddd 表示1到3位數(shù)八進制值的字符。僅在格式字符串中有效
\0ddd 表示1到3位的八進制值字符

與C語言printf()函數(shù)的不同

  • printf 命令不用加()
  • format-string 可以沒有引號,但最好加上,單引號雙引號均可,不加上運行結果偶爾異常,如
[chen@localhost tmp]$ printf "hello\n"
hello
[chen@localhost tmp]$ printf hello\n
hellon[chen@localhost tmp]$
  • 參數(shù)多于格式控制符(%)時,format-string 可以重用,可以將所有參數(shù)都轉換,即未指定格式使用前面的格式
[chen@localhost tmp]$ printf "%s\n%s%s\n" 1 2 3
1
23
[chen@localhost tmp]$ printf "%s\n" 1 2 3    #格式不夠使,借前面的格式
1
2
3
  • arguments 使用空格分隔,不用逗號。
[chen@localhost tmp]$ printf "%s\n" 1,2 3  #逗號不分隔,空格分隔
1,2
3

調試

1 bash命令調試

bash [-nvx] scripts.sh

選項與參數(shù):

-n :不要執(zhí)行 script,僅查詢語法的問題;
-v :再執(zhí)行 sccript 前,先將 scripts 的內容輸出到屏幕上;
-x :將使用到的 script 內容顯示到屏幕上,這是很有用的參數(shù)!
例如,想要執(zhí)行bash腳本,并查看bash的調用流程,可以通過以下命令:
$ bash -x test.sh

2 echo調試

echo [OPTION] STRING
-n : 輸出內容之后,不換行。默認是輸入內容之后,換行。
-e : 開啟反斜線“\”轉義功能
-E : 關閉反斜線“\”轉義功能(**默認**)。
例如,輸出“please input a number:”之后不換行。
$ echo -n "please input a number:"

3 printf

和echo一樣,printf也能用于輸出。語法格式和C語言中printf一樣。
例如,輸出“hello printf”之后換行。
$ printf "hello printf\n"

輸入輸出重定向

標準輸入,標準輸出,標準錯誤輸出
執(zhí)行一個shell命令行時通常會自動打開三個標準文件,即

  • 標準輸入文件(stdin),即shell的輸入設備(linux里設備也是文件),通常對應終端的鍵盤;
  • 標準輸出文件(stdout)為執(zhí)行命令成功時將運行的結果輸出到的文件
  • 標準錯誤輸出到文件(stderr)為執(zhí)行命令報錯時將錯誤信息輸出到的文件,這兩個文件都對應終端的屏幕。

/dev下可以看到 stdin stdout stderr三個文件分別為標準輸入,標準輸出,標準錯誤輸出,通過下面的例子可以看到 stdin stdout stderr分別連接到不同的文件

ubuntu@VM-10-194-ubuntu:/dev$ ls -all std*
lrwxrwxrwx 1 root root 15 Aug  7 09:34 stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Aug  7 09:34 stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Aug  7 09:34 stdout -> /proc/self/fd/1

輸入輸出重定即: 改變輸入/輸出數(shù)據(jù)的的讀取/輸出的默認文件(鍵盤或終端)為其他文件(普通文件,文件描述符,文件設備),而且只能是文件

常用操作符

名稱 默認文件描述符 操作符
標準輸入(stdin) 0 < ,<<,0<或0<<
0<與<等價,其他帶有文件描述符的操作符意義同理,<<代表追加
標準輸出(stdout) 1 >, >>, 1> 或 1>>
標準錯誤輸出(stderr) 2 2> 或 2>>

輸入重定向

輸入重定向是指把命令(或可執(zhí)行程序)的標準輸入重定向到指定的文件中。也就是說,輸入可以不來自鍵盤,而來自一個指定的文件。所以說,輸入重定向主要用于改變一個命令的輸入源,特別是改變那些需要大量輸入的輸入源。

格式

命令 操作符 重定向文件

示例命令

格式 說明
Command < filename Command 命令以 filename 文件作為標準輸入
Command < filename > filename2 Command 信不信以 filename 文件作為標準輸入,以 filename 2 作為標準輸出
注: 輸入(>或>>) 與 輸出(<或<<)無強制順序 即wc >test<<delim與wc <<delim >test一樣
Command << delimiter 從標準輸入中讀入,以 delimiter(任意) 為結束符,祥見示例

注: 上表格中的重定向僅在當前命令生效

wc 統(tǒng)計指定文件包含的行數(shù)、單詞數(shù)和字符數(shù)

#當只輸入wc時,回等待用戶輸入,直至 ctrl+d停止,然后統(tǒng)計行數(shù)、單詞數(shù)和字符數(shù)
ubuntu@VM-10-194-ubuntu:/tmp$ wc
123 34
23      1       3       9
# 也可將輸入重定向為某個文件
ubuntu@VM-10-194-ubuntu:/tmp$ wc < file
13 13 95
ubuntu@VM-10-194-ubuntu:/tmp$ wc <<delim
> haha
> test
> lala
> delim
 3  3 15
#或者,將結果輸出到test中
ubuntu@VM-10-194-ubuntu:/tmp$ wc >test<<delim
> haha
> test
> lala
> delim
ubuntu@VM-10-194-ubuntu:/tmp$ cat test
 3  3 15

輸出重定向

輸出重定向是指把命令(或可執(zhí)行程序)的標準輸出或標準錯誤輸出重新定向到指定文件中。這樣,該命令的輸出就不顯示在屏幕上,而是寫入到指定文件中。

輸出重定向比輸入重定向更常用,很多情況下都可以使用這種功能。例如,如果某個命令的輸出很多,在屏幕上不能完全顯示,那么將輸出重定向到一個文件中,然后 再用文本編輯器打開這個文件,就可以查看輸出信息;如果想保存一個命令的輸出,也可以使用這種方法。

格式

命令 操作符 重定向文件

注意標準輸出和標準錯誤輸出不是"一個"文件,所以有兩個輸出,只改一個的話,另一個不變,同時改變需要2>file 1>file(意思是標準輸出到file,標準錯誤輸出到file),或者>file 2>&1(表示標準輸出到file,標準錯誤輸出到標準輸出的文件即file)或者&>file (意思是把 標準輸出 和 標準錯誤輸出 都重定向到文件file中)
>>為追加輸入,即在原文件內末尾添加
示例命令

格式 說明
Command > filename 把標準輸出重定向到一個新文件中
Command >> filename 把標準輸出重定向到一個文件(追加)
Command 2> filename 把標準錯誤重定向到一個文件中
Command 2>> filename 把標準錯誤重定向到一個文件中(追加)
Command > filename 2>&1 把標準輸出和錯誤一起重定向到一個文件中
Command >> filename 2>&1 把標準輸出和錯誤一起重定向到一個文件中(追加)

注: 上表格中的重定向僅在當前命令生效

ubuntu@VM-10-194-ubuntu:/tmp$ ls vv >file
ubuntu@VM-10-194-ubuntu:/tmp$ ls vv >>file
ubuntu@VM-10-194-ubuntu:/tmp$ cat file
vv
vv

綁定重定向

前兩種重定向僅生效一次,綁定重定向即永久重定向輸入輸出文件,所有命令的輸入輸出都都來自重定向后的文件
格式

exec 操作符 重定向文件

操作符 < 0< << > 1> .... 與之前意義相同

# 將輸出綁定重定向到/tmp/test后命令的結果不會輸出到終端
ubuntu@VM-10-194-ubuntu:/tmp$ exec >/tmp/test
ubuntu@VM-10-194-ubuntu:/tmp$ ls
ubuntu@VM-10-194-ubuntu:/tmp$ ls -11
# 將輸出重定向回/dev/tty(注意必須寫完整路徑)則終端又輸出命令運行結果
ubuntu@VM-10-194-ubuntu:/tmp$ exec >/dev/tty
ubuntu@VM-10-194-ubuntu:/tmp$ ls
!  1  cal.sh  cancan  cvm_init.log  ff    net_affinity.log  sagent.pid  test  vv
0  2  can     chon    ec            file  pin               setRps.log  tty

文件描述符

文件描述符,可以理解為文件的一個數(shù)字標記

  • &0代表標準輸入文件的標記為0
  • &1 代表標準輸出文件標記為1
  • &2代表標準錯誤輸出
  • &-代表關閉與它綁定的描述符

&n 代表是已經(jīng)存在的文件描述符,在重定向時與文件地位相同,即重定向的文件也可以用文件描述符來表示

格式

#指定m描述的文件
命令 m>file
#一般為一次性重定向,綁定重定向命令為exec,
# file也可以為&n,這樣m->n->n描述的文件

示例命令

格式 說明
Command >&n 把標準輸出重定向到文件描述符 n 中,如 ls >&1 ,若要實現(xiàn)綁定重定向則Command為exec如 exec >&n
Command m>&n 把往文件描述符 m 的輸出重定向到文件描述符 n 上,2>&1,若要實現(xiàn)綁定重定向則 exec m>&n
Command <&- 關閉標準輸入同樣綁定則Command為exec
Command 2>&- 關閉標準錯誤輸出,和 2>/dev/null 有類似功效,同樣綁定則Command為exec
Command n>&- 關閉輸出文件描述符n,和 2>/dev/null 有類似功效,同樣綁定則Command為exec

ubuntu@VM-10-194-ubuntu:/tmp$ exec 6>&1
#原理: 6 -> 1 -> stdout -> /dev/tty
ubuntu@VM-10-194-ubuntu:/tmp$ exec 1>test.txt
#原理: 1->test.txt 同時 stdout -> test.txt
ubuntu@VM-10-194-ubuntu:/tmp$ ls
#原理: ls結果輸出到/tmp/test.txt了
ubuntu@VM-10-194-ubuntu:/tmp$ exec 1>&6
#原理: 1-> 6 -> /dev/tty 同時 stdout -> /dev/tty,也可直接exec 1>/dev/tty或者 exec 1>&2
ubuntu@VM-10-194-ubuntu:/tmp$ ls
cvm_init.log  net_affinity.log  sagent.pid  setRps.log  test.txt
#原理: ls結果輸出到/dev/tty即終端
ubuntu@VM-10-194-ubuntu:/tmp$ ls /dev/fd
0  1  2  3  6
#添加文件描述符后在/dev/fd里可以看到
ubuntu@VM-10-194-ubuntu:/tmp$ exec 6>&-
#
ubuntu@VM-10-194-ubuntu:/tmp$ ls /dev/fd
0  1  2  3

備注

1. > < n>等操作符可以同時出現(xiàn)在一條命令里,而且無順序要求,如
ubuntu@VM-10-194-ubuntu:/tmp$ exec 1>test 2>/dev/tty
2. 命令行前面這一條ubuntu@VM-10-194-ubuntu:/tmp$以及輸入的命令在鍵盤上的顯示好像屬于標準錯誤輸出
3. 命令 < 文件 中的命令應該能接受標準輸入 ,命令 > 文件中的命令應該有標準輸出
4. 在類Unix系統(tǒng)中,/dev/null,或稱空設備,是一個特殊的設備文件,它丟棄一切寫入其中的數(shù)據(jù)(但報告寫入操作成功),讀取它則會立即得到一個EOF,可以重定向輸出到/dev/null

其他傳遞

管道

將一個程序或命令的輸出作為另一個程序或命令的輸入,有兩種方法,一種是通過一個臨時文件將兩個命令或程序結合在一起,例如

ubuntu@VM-10-194-ubuntu:/tmp$ ls > test
ubuntu@VM-10-194-ubuntu:/tmp$ cat test
cvm_init.log
net_affinity.log
sagent.pid
setRps.log
test

另一種是Linux所提供的管道功能。

ubuntu@VM-10-194-ubuntu:/tmp$ ls | cat
cvm_init.log
net_affinity.log
sagent.pid
setRps.log
test

管道工作流程


command1正確輸出,作為command2的輸入 然后comand2的輸出作為,comand3的輸入 ,comand3輸出就會直接顯示在屏幕上面了。

通過管道之后:comand1,comand2的正確輸出不顯示在屏幕上面

注意:

  1. 管道命令只處理前一個命令正確輸出,不處理錯誤輸出
  2. 管道命令右邊命令,必須能夠接收標準輸入流命令才行

管道與重定向的區(qū)別

  1. 管道
    左邊的命令應該有標準輸出 | 右邊的命令應該接受標準輸入
    重定向
    左邊的命令應該有標準輸出 > 右邊只能是文件
    左邊的命令應該需要標準輸入 < 右邊只能是文件
  2. 管道觸發(fā)兩個子進程執(zhí)行|兩邊的程序;而重定向是在一個進程內執(zhí)行
#可以相互轉換情況
#輸入重定向
 
[chengmo@centos5 shell]$ cat test.sh| grep -n 'echo'
5:    echo "very good!";
7:    echo "good!";
9:    echo "pass!";
11:    echo "no pass!";
#"|"管道兩邊都必須是shell命令
 
 
[chengmo@centos5 shell]$ grep -n 'echo' <test.sh    
5:    echo "very good!";
7:    echo "good!";
9:    echo "pass!";
11:    echo "no pass!";
#"重定向"符號,右邊只能是文件(普通文件,文件描述符,文件設備)
 
 
[chengmo@centos5 shell]$ mail -s 'test' 8292669@qq.com <test.sh
[chengmo@centos5 shell]$ cat test.sh|mail -s 'test' 8292669@qq.com
#以上2個也相同,將test.sh內容發(fā)送到指定郵箱。
 
 
[chengmo@centos5 shell]$ (sed -n '1,$p'|grep -n 'echo')<test.sh 
5:    echo "very good!";
7:    echo "good!";
9:    echo "pass!";
11:    echo "no pass!";
#這個腳本比較有意思了。由于前面是管道,后面需要把test.sh內容重定向到 sed ,然后sed輸出通過管道,輸入給grep.需要將前面用"()"運算符括起來。在單括號內的命令,可以把它們看作一個象一個命令樣。如果不加括號test.sh就是grep 的輸入了。
 
 
#上面一個等同于這個
[chengmo@centos5 shell]$ sed -n '1,$p'<test.sh | grep -n 'echo'
5:    echo "very good!";
7:    echo "good!";
9:    echo "pass!";
11:    echo "no pass!";
 
#重定向運算符,在shell命令解析前,首先檢查的(一個命令,執(zhí)行前一定檢查好它的輸入,輸出,也就是0,1,2 設備是否準備好),所以優(yōu)先級會最高
 
 
[chengmo@centos5 shell]$ sed -n '1,10p'<test.sh | grep -n 'echo' <testsh.sh
10:echo $total;
18:echo $total;
21:     echo "ok";
#哈哈,這個grep又接受管道輸入,又有testsh.sh輸入,那是不是2個都接收呢。剛才說了"<"運算符會優(yōu)先,管道還沒有發(fā)送數(shù)據(jù)前,grep綁定了testsh.sh輸入,這樣sed命令輸出就被拋棄了。這里一定要小心使用
 
#輸出重定向
 
[chengmo@centos5 shell]$ cat test.sh>test.txt
[chengmo@centos5 shell] cat test.sh|tee test.txt &>/dev/null
#通過管道實現(xiàn)將結果存入文件,還需要借助命令tee,它會把管道過來標準輸入寫入文件test.txt ,然后將標準輸入復制到標準輸出(stdout),所以重定向到/dev/null 不顯示輸出
#">"輸出重定向,往往在命令最右邊,接收左邊命令的,輸出結果,重定向到指定文件。也可以用到命令中間。
 
 
[chengmo@centos5 shell]$ ls test.sh test1.sh testsh.sh 2>err.txt | grep 'test'
test.sh
testsh.sh
#目錄下面有:test,testsh文件,test1.sh不存在,因此將ls 命令錯誤輸出輸入到err.txt 正確輸出,還會通過管道發(fā)送到grep命令。
[chengmo@centos5 shell]$ ls test.sh test1.sh testsh.sh &>err.txt | grep 'test'
#這次打印結果是空,&代表正確與錯誤輸出 都輸入給err.txt,通過管道繼續(xù)往下面?zhèn)鬟f數(shù)據(jù)為空,所以沒有什么顯示的
 
#同樣">"輸出重定向符,優(yōu)先級也是先解析,當一個命令有這個字符,它就會與左邊命令標準輸出綁定。準備好了這些,就等待命令執(zhí)行輸出數(shù)據(jù),它就開始接收

命令替換(重音符`)

命令替換和重定向有些相似,但區(qū)別在于命令替換是將一個命令的輸出作為另外一個命令的參數(shù)

重定向必須為一個文件,而重音符``是將命令的結果作為參數(shù)傳遞例如

ubuntu@VM-10-194-ubuntu:/tmp$ echo 192.168.1.1 > file
# ping需要參數(shù),不是文件,即不能接受標準輸入,可以接受重音符運行的參數(shù),不能接受重定向的輸入文件
ubuntu@VM-10-194-ubuntu:/tmp$ ping `cat file`
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
^Z
[8]+  Stopped                 ping `cat file`
ubuntu@VM-10-194-ubuntu:/tmp$ echo 192.168.1.1 >file
ubuntu@VM-10-194-ubuntu:/tmp$ ping < file
Usage: ping [-aAbBdDfhLnOqrRUvV]...省略
##cat 可以接收文件,也可以接受參數(shù),即可以接受標準輸入
ubuntu@VM-10-194-ubuntu:/tmp$ cat file
192.168.1.1
ubuntu@VM-10-194-ubuntu:/tmp$ cat < file
192.168.1.1
ubuntu@VM-10-194-ubuntu:/tmp$ cat `echo file`
192.168.1.1

還有好多需要學的,留在下篇繼續(xù)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經(jīng)改了很多 但是錯誤還是無法避免 以后資料會慢慢更新 大...
    數(shù)據(jù)革命閱讀 13,274評論 2 33
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,659評論 19 139
  • Ubuntu的發(fā)音 Ubuntu,源于非洲祖魯人和科薩人的語言,發(fā)作 oo-boon-too 的音。了解發(fā)音是有意...
    螢火蟲de夢閱讀 100,749評論 9 468
  • 基礎命令 主要的命令和快捷鍵 Linux系統(tǒng)命令由三部分組成:cmd + [options]+[operation...
    485b1aca799e閱讀 1,224評論 0 0
  • 基礎 頭文件 #!/bin/bash 或者#!/bin/sh #!約定的標記,如IOS的Import 執(zhí)行文件時需...
    ZMJun閱讀 1,335評論 1 2

友情鏈接更多精彩內容