目錄
1.終端打印
1.1 實戰
- 使用不帶引號的echo,不能再文本中使用分號,因爲分號在bash中被用作命令定界符
- 變量替換在單引號中無效
- 雙引號中打印特殊字符需要加轉義字符:
echo "hello world\!"
- printf函數也可用於打印,類似於C語言
printf "s%" No
1.2 補充內容
- echo -n 忽略行尾的換行符
- echo -e 接收轉義序列
ian@ian-virtual-machine:~$ echo "12\t3"
12\t3
ian@ian-virtual-machine:~$ echo -e "12\t3"
12 3
- 使用轉義序列可以打印彩色輸出
echo -e "\e[1;42m Green Backgroud \e[0m"
輸出:
2. 玩轉變量
2.1 進程環境變量
查看進程運行時的環境變量可以用這個命令:
cat /proc/$PID/environ
輸出:
USER=ianLC_TIME=zh_CN.UTF-8TEXTDOMAIN=im-configXDG_SEAT=seat0XDG_SESSION_TYPE=x11SSH_AGENT_PID=1628SHLVL=0QT4_IM_MODULE=ximHOME=/home/ianDESKTOP_SESSION=ubuntuGTK_MODULES=gail:atk-bridgeGNOME_SHELL_SESSION_MODE=ubuntuLC_MONETARY=zh_CN.UTF-8DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/busIM_CONFIG_PHASE=2LOGNAME=ianGTK_IM_MODULE=ibusUSERNAME=ianXDG_SESSION_ID=2WINDOWPATH=2PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/binLC_ADDRESS=zh_CN.UTF-8XDG_RUNTIME_DIR=/run/user/1000DISPLAY=:0LANG=en_US.UTF-8XDG_CURRENT_DESKTOP=ubuntu:GNOMELC_TELEPHONE=zh_CN.UTF-8XDG_SESSION_DESKTOP=ubuntuXMODIFIERS=@im=ibusXAUTHORITY=/run/user/1000/gdm/XauthoritySSH_AUTH_SOCK=/run/user/1000/keyring/sshLC_NAME=zh_CN.UTF-8SHELL=/bin/bashQT_ACCESSIBILITY=1GDMSESSION=ubuntuLC_MEASUREMENT=zh_CN.UTF-8TEXTDOMAINDIR=/usr/share/locale/GPG_AGENT_INFO=/run/user/1000/gnupg/S.gpg-agent:0:1LC_IDENTIFICATION=zh_CN.UTF-8XDG_VTNR=2QT_IM_MODULE=ximPWD=/home/ianCLUTTER_IM_MODULE=ximXDG_DATA_DIRS=/usr/share/ubuntu:/usr/local/share:/usr/share:/var/lib/snapd/desktopXDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdgLC_NUMERIC=zh_CN.UTF-8LC_PAPER=zh_CN.UTF-8GNOME_DESKTOP_SESSION_ID=this-is-deprecatedXDG_MENU_PREFIX=gnome-SESSION_MANAGER=local/ian-virtual-machine:@/tmp/.ICE-unix/1533,unix/ian-virtual-machine:/tmp/.ICE-unix/1533DESKTOP_AUTOSTART_ID=10692a68641ba1de1158631729595816000000015330000GIO_LAUNCHED_DESKTOP_FILE=/usr/share/applications/org.gnome.Shell.desktopGIO_LAUNCHED_DESKTOP_FILE_PID=1
2.2 常見變量使用
- 變量賦值方法:var=value, var = value的寫法是錯的
- 可以在printf或者echo的雙引號中引用變量
- 單引號不會被擴展,會按照原樣式顯示
ian@ian-virtual-machine:~$ echo $a
1
ian@ian-virtual-machine:~$ echo '$a'
$a
2.3 補充內容
- 獲取字符串長度:${#var}
ian@ian-virtual-machine:~$ echo ${#a}
1
- 識別當前使用shell:echo $0 或者 echo $SHELL
- 檢測是否爲超級用戶:echo $UID,返回值爲0則爲root
- 修改bash提示符:設置PS1變量,例如,PS1="Ian>"
ian@ian-virtual-machine:~$ PS1="Ian>" Ian>
3. 使用函數添加環境變量
當需要經常安裝軟件,將路徑加入到path中時,可以在bashr中添加一個添加路徑的函數。
比如常見的加入path的命令爲:
export PATH=/home/ian:$PATH
echo $PATH
/home/ian:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
加入bashrc的函數:
prepend() { [ -d "$2" ] && eval $1=\"$2':'\$$1\" && export $1; }
函數先檢查第二個參數是否存在,如果存在
調用方法:
Ian>echo $PATH
/home/ian:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
Ian>prepend PATH /home/ian/Videos/
Ian>echo $PATH
/home/ian/Videos/:/home/ian:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
4. shell數學計算
可以使用let,(()),和[]執行基本的算術操作,expr和bc可以用於高級操作
- 基本運算
Ian>a=4 Ian>b=5 Ian>let result=a+b Ian>echo $result 9 Ian>result=$[ a + b ] Ian>echo $result 9 Ian>result=$(( a + 5)) Ian>echo $result 9 Ian>result=$(expr $a + 5) Ian>echo $result 9
不過,(())的寫法在一些編程標準中是不允許的。基礎運算只支持整數,不支持浮點數
-
bc可以進行浮點計算和高級函數的計算
Ian>echo "$a * 0.56"|bc 2.24 Ian>echo "sqrt(100)" |bc 10
5. 文件描述符及重定向
5.1 重定向默認描述符
系統保留的文件描述符:
- 0:stdin(標準輸入)
- 1:stdout(標準輸出)
- 2:stderr(標準錯誤)
5.2 如何重定向
使用>或者>>可以將標準輸出重定向。
將標準錯誤重定向到文件:
Ian>ls + 2>a.log
Ian>cat a.log
ls: cannot access '+': No such file or directory
可以將標準輸出和標準錯誤重定向到不同的文件:
ls + 2>a.log 1>b.log
將stderr轉換成stdout之後重定向到一個文件:
ls + >a.log 2>&1
ls + >/dev/null 2>&1 #不輸出任何信息
關於2>&1的含義可見
https://blog.csdn.net/sc9018181134/article/details/88432070
5.3 擴展方法
tee命令既可以將stdin中的數據重定向到文件,還可以提供一份重定向數據的副本作爲後續的stdin(主要用於將標準輸出重定向到文件中)
Ian>cat *.log *.lsodfj|tee a.out|cat -n
cat: '*.lsodfj': No such file or directory
1 ls: cannot access '+': No such file or directory
2 blog file
Ian>cat a.out
ls: cannot access '+': No such file or directory
blog file
當只需獲取上一個命令的輸出,而不需要輸出到文件時,可以用tee -
Ian>echo who is this|tee -|cat -n
1 who is this
5.4 自定義文件描述符
文件描述符是一種用於訪問文件的抽象指示器。具體解釋:https://www.cnblogs.com/alan666/p/8311890.html
可以使用exec創建自定義的文件描述符;
Ian>touch input.txt
Ian>exec 3<input.txt
Ian>echo test input line >input.txt
Ian>cat <&3
test input line
如果需要再次讀取就需要重新用exec分配。
6. 數組與關聯數組
6.1 數組
- 定義數組
Ian>a=(1 2 3 4 5) Ian>b[1]=1
- 打印數組
Ian>echo ${a[*]}
1 2 3 4 5
Ian>echo ${b[*]}
5 1
Ian>echo ${a[0]}
1
6.2 關聯數組(類似python中的字典)
- 定義關聯數組,賦值關聯數組,顯示關聯數組:
Ian>declare -A ass_a Ian>ass_a=([index1]=val1 [index2]=val2) Ian>ass_a[index3]=val3 Ian>echo ${ass_a[*]} val1 val2 val3 Ian>echo ${ass_a[index1]} val1
- 列出數組索引(key值)
Ian>echo ${!ass_a[*]}
index1 index2 index3
7. 使用別名
- alias創建,刪除別名
Ian>alias hls='hadoop fs -ls' Ian>hls hadoop: command not found Ian>alias hls= Ian>hls Ian>
- 忽略別名使用,在命令之前加反斜槓'\'進行轉義
Ian>alias hls1='hadoop fs -ls' Ian>\hls1 Command 'hls1' not found, did you mean: command 'hls' from deb hfsutils Try: sudo apt install <deb name>
8.日期和延時
- 讀取,設置日期和時間:
Ian>date #獲取日期
Thu Apr 9 21:15:35 CST 2020
Ian>date +%s #獲取時間戳
1586438156
Ian>date --date "Thu Apr 9 21:15:35 CST 2020" +%s #將日期轉換爲時間戳
1586438135
Ian>date --date "Thu Apr 9 21:15:35 CST 2020" +%A #將日期按照星期打印
Thursday
- 格式串+可以作爲date的參數,按照相應格式打印出日期,比如:
Ian>date +%A Thursday Ian>date "+%d %B %Y" 09 April 2020
-
日期格式列表如下:
日期:
%a : 星期幾 (Sun..Sat)
%A : 星期幾 (Sunday..Saturday)
%b : 月份 (Jan..Dec)
%B : 月份 (January..December)
%c : 直接顯示日期和時間
%d : 日 (01..31)
%D : 直接顯示日期 (mm/dd/yy)
%h : 同 %b
%j : 一年中的第幾天 (001..366)
%m : 月份 (01..12)
%U : 一年中的第幾周 (00..53) (以 Sunday 爲一週的第一天的情形)
%w : 一週中的第幾天 (0..6)
%W : 一年中的第幾周 (00..53) (以 Monday 爲一週的第一天的情形)
%x : 直接顯示日期 (mm/dd/yy)
%y : 年份的最後兩位數字 (00.99)
%Y : 完整年份 (0000..9999)時間:
% : 印出冒號
% %n : 下一行
%t : 跳格
%H : 小時(00..23)
%I : 小時(01..12)
%k : 小時(0..23)
%l : 小時(1..12)
%M : 分鐘(00..59)
%p : 顯示本地 AM 或 PM
%r : 直接顯示時間 (12 小時制,格式爲 hh:mm:ss [AP]M)
%s : 從 1970 年 1 月 1 日 00:00:00 UTC 到目前爲止的秒數 %S : 秒(00..61)
%T : 直接顯示時間 (24 小時制)
%X : 相當於 %H:%M:%S
%Z : 顯示時區
9. 調試腳本
- bash -x
bash -x命令可以打印出所執行的每一行命令及當前的狀態。例如新建一個腳本:
#!/bin/bash
#script.sh
for i in 1 2 3;
do
echo $i
done
echo "done"
使用bash -x 命令:
Ian>bash -x script.sh
+ for i in 1 2 3
+ echo 1
1
+ for i in 1 2 3
+ echo 2
2
+ for i in 1 2 3
+ echo 3
3
+ echo done
done
- set -x和set +x
這兩個命令可以設置在腳本的中間,只調試部分腳本(但是在Bash4.1.10後就不好使了):
修改script腳本:
#!/bin/bash
for i in 1 2 3;
do
set -x
echo $i
set +x
done
echo "done script"
輸出:
Ian>bash script.sh
+ echo 1
1
+ set +x
+ echo 2
2
+ set +x
+ echo 3
3
+ set +x
done script
- 自定義顯示調試信息:調用_DEBUG參數。修改腳本如下:
#!/bin/bash #script.sh function DEBUG() { [ "_DEBUG" == "on" ] && $@ || echo "debug" } for i in 1 2 3; do DEBUG echo $i done echo "done script"
調用:
Ian>bash script.sh debug debug debug done script
- 使用shebang調試:可將#!/bin/bash修改成爲#!/bin/bash -xv
10. 函數和參數
- 定義函數
#!/bin/bash function fname1() { echo 1; } fname2() { echo 2; } fname3() { echo $1; } fname1 fname2 fname3 3
輸出:
Ian>bash func.sh 1 2 3
- 導出函數:可以像環境變量一樣導出函數。
export -f fname1
在原先的腳本中加入一行,然後source腳本,就可以調用函數:
Ian>source func.sh
1
2
3
Ian>fname1
1
- 讀取命令返回值:$?
Ian>ls func.sh script.sh Ian>echo $? 0
11.管道:將命令序列的 輸出讀入變量
- 管道使用
ls | cat -n > out.txt
將ls的結果傳入給cat -n
- 獲取管道相連的命令序列的輸出:$(cmd)
Ian>a=`ls | cat -n`
Ian>echo $a
1 func.sh 2 out.txt 3 script.sh
Ian>b=$(ls | cat -n)
Ian>echo $b
1 func.sh 2 out.txt 3 script.sh
- 定義一個子進程
命令在子進程執行,對當前任務沒有任何影響:
#腳本
#!/bin/bash
pwd
(cd /home; pwd; ls)
pwd
#調用
Ian>sh prp.sh
/home/ian/test
/home
ian
/home/ian/test
12. read命令
read用於從鍵盤或者標準輸入中讀取文本。
- 從輸入中讀取n個字符:read -n 2 var
Ian>vim prp.sh
Ian>read -n 2 var
hiIan>echo $var
hi
- 無回顯方式讀取:read -s
- 顯示提示信息讀取:read -p "input:" var
- 特定時限內讀取:read -t 10 var
- 用特殊的定界符作爲輸入行的結束:read -d ":" var
Ian>read -d ":" var
fdashfhas
fnaihfo
fjap'ja:Ian>echo $var
fdashfhas fnaihfo fjap'ja
13. 運行命令直至成功
- 定義一個repeat函數
repeat()
{
while true;
do
$@ && return
done
}
函數定義了一個while循環,如果傳入函數返回爲true,則返回,否則一直執行.
也可以用":"代替true
14.字段分隔符和迭代器
- 內部字段分隔符(IFS)設置當前文本的分隔符(默認爲空格)。
Ian>echo $IFS
Ian>data="1,2,3"
Ian>for item in $data;do echo item:$item; done
item:1,2,3
Ian>IFS=,
Ian>for item in $data;do echo item:$item; done
item:1
item:2
item:3
- shell中生成數字或者字母列表
Ian>echo {1..3}
1 2 3
Ian>echo {a..e}
a b c d e
15. 比較與測試
- if 可以用於測試:
Ian>if true; then echo 1; fi
1
Ian>if false; then echo 1; elif true; then echo 2; else echo 3; fi
2
- 算數比較
注意在[]與操作符之間需要有一個空格,不然會報錯
Ian>if [ $var -eq 0 ]; then echo 0; else echo 1; fi
0
-gt:大於
-lt:小於
-ge:大於等於
-le:小於等於
-a:邏輯與
-o:邏輯或
- 文件系統相關測試
-e filename 如果 filename存在,則爲真
-d filename 如果 filename爲目錄,則爲真
-f filename 如果 filename爲常規文件,則爲真
-L filename 如果 filename爲符號鏈接,則爲真
-r filename 如果 filename可讀,則爲真
-w filename 如果 filename可寫,則爲真
-x filename 如果 filename可執行,則爲真
-s filename 如果文件長度不爲0,則爲真
-h filename 如果文件是軟鏈接,則爲真
- 字符串比較
[[ $str1 == $str2 ]]
>,=,!=,-z(空字符串),-n(非空字符串)
- 邏輯運算
&&,||