linux shell腳本攻略 第一章 小試牛刀 基本操作,變量,函數,管道等

目錄

 

1.終端打印

1.1 實戰

1.2 補充內容

2. 玩轉變量

2.1 進程環境變量

2.2 常見變量使用

2.3 補充內容

3. 使用函數添加環境變量

4. shell數學計算

5. 文件描述符及重定向

5.1 重定向默認描述符

5.2 如何重定向

5.3 擴展方法

5.4 自定義文件描述符

6. 數組與關聯數組

6.1 數組

6.2 關聯數組(類似python中的字典)

7. 使用別名

8.日期和延時

9. 調試腳本

10. 函數和參數

11.管道:將命令序列的 輸出讀入變量

12. read命令

13. 運行命令直至成功

14.字段分隔符和迭代器

15. 比較與測試


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(非空字符串)

  • 邏輯運算

&&,||

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章