echo
- 回聲,用於列印輸出工作
- -n: 可以不換行
- -e:對字元進行轉義,\t ===》 enable
printf
- printf “%d,%s\n” 10 “你好”
- 注意10 和 “你好” 兩個引數之間,沒有逗號
管道|
使用| 可以將多個命令拼接在一起
cat /etc/passwd | grep itcast | cut -d: -f4 1000
原理:將前一個命令的標準輸出作為後一個命令的標準輸入
標準錯誤輸出是不會被管道傳遞的
cp | grep information. # 這個是不生效的 cp --help | grep existing --color #這個是正確用法
並不是所有的命令都可以接受|的資料,比如說ls
find ../../01-shell-basic/ | ls
需求:實現一個接收管道輸出的命令:讀取標準輸入,將標準輸入的資料轉成大寫,然後輸出:
#include<stdio.h> #include<ctype.h> int main() { int ch=getchar(); while(ch != EOF) { putchar(toupper(ch)); ch = getchar(); } return 0; }
經常與more和less使用
- more,只可以單向查閱
- less可以雙向查閱
- ctrl + f(前),ctrl+B(後)
tee
作用之一:
將標準輸出重新輸出到指定的檔案
公司伺服器列印log,希望能夠在螢幕上列印,同時儲存到檔案:
ping www.baidu.com | tee ping.log
如果想動態檢視ping.log檔案內容
- vim ping.log, 然後輸入:e,可以隨時重新整理
- tail -f ping.log,動態重新整理
- alias tailf=tail -f
作用之二:
當修改了一個檔案很多內容,但是沒有修改許可權的時候,可以直接使用tee命令來啟用sudo 許可權,從而完成修改
重定向
cmd > 1.txt , 將輸出寫入到1.txt,每一次都是重新覆蓋,等同於: cmd 1> 1.txt(常用)
cmd > > 1.txt,將輸出追加到1.txt
>, >> 兩者只能將標準輸出重定向到檔案,而標準錯誤輸出無法直接寫入
案例:
$ cp > cp.txt cp: missing file operand Try 'cp --help' for more information. cat cp.txt 返回空
檔案描述符:
- 標準輸入檔案描述符:0
- 標準輸出檔案描述符:1
- 標準錯誤輸出檔案描述符:2
如果想將錯誤的資訊重定向到檔案,需要使用檔案描述符2
cp 2> cperr.txt #2> 表示對錯誤資訊重定向
==如何將正確輸出和錯誤輸出都寫入到一個檔案中?(最常用)==
cp > /tmp/cperr1.txt 2>&1
寫一段c程式碼,裡面同時輸出:stdout, stderr
#include<stdio.h> int main() { //寫一段c程式碼,裡面同時輸出:stdout, stderr fprintf(stdout, "this is stdout\n"); //fd 1 fprintf(stderr, "this is stderr\n"); //fd 2 return 0; }
結果:
使用重定向進行輸入
cmd < file
cat < /etc/passwd
其他:
- cmd < &fd
- cmd > &fd
- cmd < &-
函式
==沒有引數列,沒有返回值,return返回的是狀態碼,使用$?檢視==
定義函式:
function test1() { #這個return的值,表示這個函式之後之後返回的狀態碼,而不出返回值, #不能通過a=test()來獲取100值 #可以通過echo $?來獲取 return 100 } #function去掉 test() { } #去掉括號 function test { } #function和()至少保留一個,否則無法識別成函式ss
案例:
#!/bin/bash function test1() { a=200 #a=100 #這個return的值,表示這個函式之後之後返回的狀態碼,而不出返回值, #不能通過a=test()來獲取100值 #可以通過echo $?來獲取 if [ $a -eq 100 ]; then return 0 else echo "hello test1" return 100 fi } #function去掉 test2() { echo "hello test2" } #去掉括號 function test3 { echo "hello test3" #如果函式沒有return值,那麼最後一條執行命令的狀態碼,就是這個函式的狀態碼 }
#function和()至少保留一個,否則無法識別成函式ss
v1=test1
if [ $? -eq 0 ];then
echo “test1執行成功! a=100”
else
echo “test1執行之後,a!=100”
fi
#echo “test1 的返回狀態碼:” $?
#echo “v1 : “ “$v1”
test2
test3
![](http://qiniuyun.quancundexiwang.wang/1585709515511.png)
3. 小結:
1. 執行狀態$?看return的返回值,如果沒有返回值,則以最後一條命令的返回值為準
```sh
test2()
{
echo "hello test2"
cp #echo $? 1
}
```
2. return修飾的狀態碼只能是數字
```sh
function test3
{
echo "hello test3"
#./functest.sh: line 26: return: beijing: numeric argument required
return "beijing" #這是錯誤的用法,必須是數字
}
```
4. 函式引數:
1. 呼叫方法與命令一樣,也是$1, $2 ..
```sh
test4()
{
echo "test4 函式引數為: $1, $2"
}
test4 "hello" "world"
```
5. 案例:遞迴遍歷指定目錄的檔案!
```sh
#!/bin/bash
#案例:遞迴遍歷指定目錄的檔案!
#目錄由使用者通過命令列傳入:
#./recursive.sh ..
recursive()
{
#接收使用者輸入的目錄
#currDir="$1"
local currDir="$1"
echo "====> 當前目錄為:" "$currDir"
#遍歷當前目錄
for i in `ls $currDir`
do
#這樣才是有效的路徑,後續才能正確判斷性質
#item="$currDir+"/"+$i" <<=== 這是錯誤的, /usr/+/+test.txt
item="$currDir/$i"
#echo "item: " $item
#如果i是檔案,則列印
if [ -f "$item" ]; then
echo "檔案找到: $item"
elif [ -d "$item" ];then
#如果i是資料夾,則遞迴遍歷
echo "資料夾找到:" "$item"
recursive $item
else
echo "未知檔案:" "$item"
fi
done
}
#判讀輸入引數的個數
if [ $# -ne 1 ];then
echo "Usage: recursive <檔案目錄>"
exit
fi
recursive $1
除錯
shell除錯引數:
-n 幫助我們快速檢查指令碼的語法,而不是逐條執行
指令碼如果很大,中間執行過程很長,如果不能實現發現指令碼錯誤,會浪費時間
bash -n ./recursive.sh
-x,執行指令碼的同時將程式碼執行過程列印到螢幕,便於追蹤
bash -x recursive.sh ==》 作用於整個指令碼
可以在程式碼中,對指定的程式碼段進行除錯
set -x ==> 啟動除錯
xxxx
set +x ==> 停止除錯
-v,一邊執行指令碼,一邊列印錯誤輸出(很少用)
shift 8 ==> *, 快速定位當前游標所值單詞(向下尋找,n)
shift 3 ==> #, 快速定位當前游標所值單詞(向上尋找,n)
以S開頭的字串
^: 可以限定一個字元開頭
目標:ShelloShello world 表示式:^Shello
以數字結尾的字串
$:可以限定結尾
表示數字方式:
- [0123456789]
- [0-9]
目標:helloworld9 表示式:helloworld[0-9]$
匹配空字串(沒有任何字元)
- ^$
字串只包含三個數字
- 三個數字:[0-9][0-9][0-9]
字串只有3到5個字母
- 字母表示:
- [a-zA-Z], 中間不要加空格
- 三個到五個字母:[a-zA-Z]{3,5}
- 重複次數{m, n}:
- 匹配前面修飾字元的次數,最少m次,最多n次
- 字母表示:
匹配不是a-z的任意字元
- ^ 在[]內部的時候,表示取反(注意,不是限定開頭)
- ^[^0-9] : 以非數字開頭的字元
- 內反,外頭
- [^a-z] <<<===
字串有0到1個數字或者字母或者下劃線
表示0-1的方法
- {0,1}
- ? : 表示0,1個
[a-zA-Z0-9_]?
內容 hello hello1 hello* 正則: hello[a-zA-Z0-9_]? 匹配結果: hello hello1 hello
字串有1個或多個空白符號(\t\n\r等)
\s ==》 代表空格
+:一個或多個
內容:hello world 正則:hello\s+world 結果:hello world
字串有0個或者若干個任意字元(除了\n)
.: 點,代表任意字元,除了\n
*:星號,重複前一個字元0-n次
匹配任意字元,任意次數:通常做法,是: .* ==> 相當於萬用字元裡面的 *
內容:hello asdfaasdfasdfadfasdfasdf asdfasdfasdf world 正則:hello.*world 結果:hello asdfaasdfasdfadfasdfasdf asdfasdfasdf world
.{,} ==> 與 .*效果相同
小結:
- ? ===> 重複前面一個字元0-1
- + ===> 重複前面一個字元1-n
- * ===> 重複前面一個字元0-n
- . ===> 表示任意字元
- ^ ===> 限定以某個字元開頭
- [^a-z] ===> 在方括號內,表示取反(非a-z的任意字元)
- $ ===> 限定以某個字元結尾
- 數字 ====》 [0123456789] 或[0-9]
- 字母 ===> [abcd] [a-zA-Z]
匹配0或任意多組ABC,比如ABC,ABCABCABC
- 使用()進行分組,組成新的匹配單元
- (ABC)*
字串要麼是ABC,要麼是123
(ABC|123)
內容: ABC ABCABCABCD 123456 hellowlrd
正則:(ABC|123)
```
字串只有一個點號
- ^\.$
匹配十進位制3位整數 :
- 0~999 , 5, 10 , 200, 999
- 分段匹配:
- 一位數:
- [0-9]
- 二位數:
- [1-9][0-9]
- 三位數:
- [1-9][0-9]{2}
- 整合:
- ^ ([0-9]|[1-9][0-9]{1,2})$
- 一位數:
匹配0-255的整數, ip地址
- 分段
- 一位:[0-9]
- 二位:[1-9][0-9]
- 三位:
- 100- 199
- 1[0-9]{2}
- 200-249
- 2[0-4][0-9]
- 250-255
- 25[0-5]
- 100- 199
- 整合:
^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$
- 192.168.1.1
- 分段
匹配埠號
- 0~65536
email
[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?
三種正規表示式:
基礎正則:(不使用) ==》 +?* 都當成普通字元來處理
擴充套件正則:(我們預設使用這個)==》 +?* 當成特殊字元
Perl正則:
+?*是特殊字元
\d ==》 數字 [0-9]
\w ==> 字元[a-zA-Z]
用法\d{3}\w 可以匹配:212c
sort(排序)
-f 忽略字元大小寫
-n 按照數值比較
-t 分割字元
-k 指定分割之後比較的欄位
-u 只顯示一次
-r 反向排序
使用:分割之後,擷取第三段,以數字的值進行比較,反向列印
sort passwd -t: -k3 -n -r
uniq(刪除重複)
uniq.txt
xiaoliu 99 man 25
xiaowen 98 man 24
xiaoliu 99 man 25
去重方式,需要重複的兩行挨著才能去重,一般和sort配合使用
cat uniq.txt | sort | uniq
wc
-l: 統計檔案的行數 <==最常用
-c:統計字元
-w:統計單詞數量
duke ~$ wc /etc/passwd -l
32 /etc/passwd
duke ~$ wc /etc/passwd -c
1694 /etc/passwd
duke ~$ wc /etc/passwd -w
49 /etc/passwd
grep
grep [options]
主要引數: grep --help可檢視
-c:只輸出匹配行的計數。
-i:不區分大小寫。
-h:查詢多檔案時不顯示檔名。
-l:查詢多檔案時只輸出包含匹配字元的檔名。
-n:顯示匹配行及 行號。
-s:不顯示不存在或無匹配文字的錯誤資訊。
-v:顯示不包含匹配文字的所有行。
--color=auto :可以將找到的關鍵詞部分加上顏色的顯示。
-r: 表示遞迴查詢
-i 忽略大小寫,NOLOGIN一行也列印了
grep -i nologin passwd --color
使用擴充正則[0-9].*
grep -i "[0-9].*bin" passwd --color
如果想使用Perl正則,需要指定-P開關
grep -i -P "\d.*bin" passwd --color
使用-r進行遞迴查詢
grep -i -P "\d.*bin" * --color -r
cat /etc/passwd | grep root
find
語法:
find pathname -options [-print -exec -ok ...]
- 通過名字查詢
find ./shell -name "*.txt"
- 通過許可權查詢
find ./shell/ -perm 755
- 通過型別查詢
find ./shell -type f "*.txt" #檔案型別
find ./shell/ -type d -name "*.txt" #資料夾型別
-type 查詢某一型別的檔案,諸如:
b - 塊裝置檔案。
d - 目錄。
c - 字元裝置檔案。
p - 管道檔案。
l - 符號連結檔案。
f - 普通檔案。
- 指定查詢深度
find / -maxdepth 2 -type d
- 不區分檔名字大小寫,使用-iname
find ./shell -type f -iname "*.txt"
對find查詢到的檔案,進行處理,使用
-exec: 直接執行
find ./shell -type f -iname "*.txt" -exec rm {} \; {} 替換為傳入的資料 \; 表示命令結束
-ok:逐個確認
find ./shell -type f -iname "*.txt" -ok rm {} \;
按照日期查詢
-atime : 訪問時間 -mtime: 修改時間, 內容修改 -ctime: 不是建立時間,而是狀態修改時間,許可權,所有者
find ./shell/ -mtime +1 -1: -n表示在n天之內修改的 +1: +n表示在n天以前修改的
引數列表:
-name 按照檔名查詢檔案。
-perm 按照檔案許可權來查詢檔案。
-size n:[c] 查詢檔案長度為n塊的檔案,帶有c時表示檔案長度以位元組計。
-depth 在查詢檔案時,首先查詢當前目錄中的檔案,然後再在其子目錄中查詢。
-prune 使用這一選項可以使find命令不在當前指定的目錄中查詢,如果同時使用-depth選項,那麼-prune將被
find命令忽略。
-user 按照檔案屬主來查詢檔案。
-group 按照檔案所屬的組來查詢檔案。
-mtime -n +n 按照檔案的更改時間來查詢檔案,-n表示檔案更改時間距現在n天以內,+n表示檔案更改時間距現在
n天以前。find命令還有-atime和-ctime 選項,但它們都和-m time選項。
-nogroup 查詢無有效所屬組的檔案,即該檔案所屬的組在/etc/groups中不存在。
-nouser 查詢無有效屬主的檔案,即該檔案的屬主在/etc/passwd中不存在。
-newer file1 ! file2 查詢更改時間比檔案file1新但比檔案file2舊的檔案。
-fstype 查詢位於某一型別檔案系統中的檔案,這些檔案系統型別通常可以在配置檔案/etc/fstab中找到,該配
置檔案中包含了本系統中有關檔案系統的資訊。
-mount 在查詢檔案時不跨越檔案系統mount點。
-follow 如果find命令遇到符號連結檔案,就跟蹤至連結所指向的檔案。
pathname: find命令所查詢的目錄路徑。例如用.來表示當前目錄,用/來表示系統根目錄,遞迴查詢。
-print: find命令將匹配的檔案輸出到標準輸出。
-exec: find命令對匹配的檔案執行該引數所給出的shell命令。相應命令的形式為'command' {} \;,注意{}內部無空格,和\;之間含有一個空格分隔符。
-ok: 和-exec的作用相同,只不過以一種更為安全的模式來執行該引數所給出的shell命令,在執行每一個命令之前,都會給出提示,讓使用者來確定是否執行。只有使用者明確輸入y才會執行後邊的語句
head、tail、scp、xargs、sed、awk
本作品採用《CC 協議》,轉載必須註明作者和本文連結