Linux系列:shell編程之變量
1、shell的介紹
Shell 本身是一個用c語言編寫的程序,它是用戶使用Unix/linux的橋梁,用戶的大部分工作都是通過Shell完成的。
Shell 既是一種命令語言,又是一種程序設計語言:作為命令語言,它交互式地解釋和執行用戶輸入的命令;作為程序設計語言,它定義了各種變量和參數,并提供了許多在高級語言中才具有的控制結構,包括循環和分支。
Shell 它雖然不是Unix/Linux系統內核的一部分,但它調用了系統核心的大部分功能來執行程序、建立文件并以并行的方式協調各個程序的運行。Shell 是用戶與內核進行交互操作的一種接口,目前最流行的Shell稱為bash Shell(Bourne Again Shell)。
Shell是一門編程語言(解釋型的編程語言,即shell腳本(就是在用linux的shell命令編程),Shell 腳本程序從腳本中一行一行讀取并執行這些命令,相當于一個用戶把腳本中的命令一行一行敲到Shell提示符下執行。
Shell是一種腳本語言,那么,就必須有解釋器來執行這些腳本。Unix/Linux上常見的shell腳本解釋器有bash、sh、csh、ksh等,習慣上把它們稱作一種Shell。
我們常說有多少種Shell,其實說的是Shell腳本解釋器,可以通過cat /etc/shells命令查看系統中安裝的shell,不同的shell可能支持的命令語法是不相同的。
sh是Unix標準默認的shell,由Steve Bourne 開發,是Bourne Shell的縮寫。
bash是Linux標準默認的shell,由Brian Fox 和Chet Ramey共同完成,是Bourne Again Shell的縮寫。
shell本身支持的命令并不多,內部命令一共有40個,但是它可以調用其他的程序,每個程序就是一個命令,這使得Shell命令的數量可以無限擴展,其結果就是Shell的功能非常強大,完全能夠勝任Linux的日常管理工作,如文本或字符串檢索、文件的查找或創建、大規模軟件的自動部署、更改系統設置、監控服務器性能、發送報警郵件、抓取網頁內容、壓縮文件等。
# 查看系統中安裝的shell [hadoop@image_boundary ~]$ cat /etc/shells /bin/sh /bin/bash /sbin/nologin /bin/dash
2、shell語言
shell腳本代碼通常寫在普通文本文件中,通常以.sh結尾,雖然不是強制要求,但希望大家最好這么做。
// vim是創建并打開了一個文件。 // a.sh存在,就是打開該文件; // a.sh不存在,就是創建該文件。 [root@image_boundary ~]# vim a.sh
上述命令:創建并打開了a.sh這個文件。
我們在該腳本中寫入如下兩行代碼。
// 一般在一個shell腳本的首行需要輸入【#!/bin/bash】這句代碼。 // 【#!/bin/bash】表示設置默認解釋器類型。 // 但是如果【指定解釋器執行】該腳本時,該行無效。 #!/bin/bash echo "Hello World"
操作如下:
[root@image_boundary ~]# sh a.sh Hello World [root@image_boundary ~]# bash a.sh Hello World
操作如下:
[root@bigdata111 ~]# source a.sh aa [root@bigdata111 ~]# . a.sh aa
注意1:source命令也稱為“點命令”也就是一個點符號(.),是bash的內部命令。
注意2:source命令通常用于重新執行剛修改的初始化文件,使之立即生效,而不必注銷并重新登錄。
注意3:.和腳本名稱之間是有空格的。
# 1 先確保該shell腳本文件有執權限 # chmod命令可以修改可讀、可寫、可執行的權限 chmod # 2 相對路徑執行法(每次執行,必須切換到文件所在目錄) # 這里的點(.)指的是“當前路徑”。 ./腳本文件名 # 3 絕對路徑執行法(只要有權限,什么路徑下都可以執行) /root/腳本文件名
操作如下:
// 修改該文件的權限,使其具有可執行的權限。 [root@image_boundary ~]# chmod 744 a.sh [root@image_boundary ~]# ll total 4 -rwxr--r--. 1 root root 31 Oct 18 09:18 a.sh // 相對路徑執行:必須切換到該文件的目錄當中去,才可以執行。 [root@image_boundary ~]# ./a.sh Hello World // 絕對路徑執行:在任何地方都可以執行。 [root@image_boundary ~]# /root/a.sh Hello World
3、變量
// set:查看所有系統變量 [root@image_boundary ~]# set // 常用的系統變量:$PWD $PATH $SHELL $USER $HOME
系統變量可以通過set命令查看,用戶環境變量可以通過env查看。
// echo $PATH :查看Linux中配置過的環境變量 [root@image_boundary ~]# echo $PATH /usr/local/tomcat/apache-tomcat-8.5.45/bin:/usr/local/java/jdk1.8.0_73/bin:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin // echo $PWD :顯示當前位置的絕對路徑 [root@image_boundary ~]# echo $PWD /root // echo $USER : 顯示當前你是哪一個用戶登陸的虛擬機 [root@image_boundary ~]# echo $USER root [huangwei@image_boundary root]$ echo $USER huangwei // echo $HOME : 顯示用戶的家目錄 [root@image_boundary ~]# echo $HOME /root [huangwei@image_boundary root]$ echo $HOME /home/huangwei // echo $SHELL : 顯示linux系統默認的shell [root@image_boundary ~]# echo $SHELL /bin/bash
語法格式:變量名=值 注意1:在shell腳本中定義變量,等號兩側,絕對不能有空格; 注意2:值中有空格,需要使用引號; 注意3:單引號會內容脫意,雙引號可以識別變量; 注意4:變量緊挨著其它單詞,可以使用${A}來獲取變量A的值;
// shell中定義變量,等號兩側絕對不能有空格; [root@bigdata111 ~]# A = 12 bash: A: command not found [root@bigdata111 ~]# A=12 // 使用$號,可以獲取變量的值; [root@bigdata111 ~]# echo $A 12 [root@bigdata111 ~]# A=abc [root@bigdata111 ~]# echo $A abc [root@bigdata111 ~]# A="abc" [root@bigdata111 ~]# echo $A abc // 值中用空格,值需要使用引號引起來; [root@bigdata111 ~]# A=ab c -bash: c: command not found [root@bigdata111 ~]# A="ab c" [root@bigdata111 ~]# echo $A ab c
[root@bigdata111 ~]# A="Chen Li" [root@bigdata111 ~]# B='I love $A' // 單引號會導致內容脫意,雙引號可以識別變量; [root@bigdata111 ~]# echo $B I love $A [root@bigdata111 ~]# B="I love $A" [root@bigdata111 ~]# echo $B I love Chen Li
// 變量緊挨其它單詞,會導致$C無法正常取值; [root@bigdata111 ~]# C="dog" [root@bigdata111 ~]# D="Those are $Cs" [root@bigdata111 ~]# echo $D This are // 想要變量與其它單詞區分,可以使用${C}; [root@bigdata111 ~]# D="Those are ${C}s" [root@bigdata111 ~]# echo $D Those are dogs // 注意以下幾種寫法的不同點; [root@image_boundary ~]# A="Dog" // a放在$A前面:a$A [root@image_boundary ~]# B="Those are a$A" // a放在$A后面:$Aa; [root@image_boundary ~]# C="Those are $Aa" [root@image_boundary ~]# echo $B Those are aDog [root@image_boundary ~]# echo $C Those are
1)撤銷變量:unset 變量名; 2)設置只讀變量:readonly 變量名=值; 注意:設置只讀變量后,修改、撤銷只讀變量,會報錯。
[root@image_boundary ~]# A=12 [root@image_boundary ~]# echo $A 12 // 撤銷變量后,變量輸出為空; [root@image_boundary ~]# unset A [root@image_boundary ~]# echo $A [root@image_boundary ~]#
[root@image_boundary ~]# readonly A=100 // 修改只讀變量,會報錯; [root@image_boundary ~]# A=666 -bash: A: readonly variable // 撤銷只讀變量,會報錯; [root@image_boundary ~]# unset A -bash: unset: A: cannot unset: readonly variable
4、案例:變量的使用(有點意思的一個案例)
寫兩個腳本,在a.sh中調用b.sh執行,那我們想知道a腳本能不能獲取到b腳本的變量,同時b腳本能不能獲取到a腳本的變量?
// 腳本a.sh中的內容; #!/bin/bash A="A in a.sh" echo $A echo $B /root/b. sh // 腳本b.sh中的內容; #!/bin/bash B="B in b. sh" echo $B echo $A
使用cat命令分別查看這兩個腳本文件中的內容。
[root@bigdata111 ~]# chmod 755 a.sh [root@bigdata111 ~]# chmod 755 b.sh
可以看到,a.sh和b.sh都有了可執行權限。
[root@bigdata111 ~]# sh a.sh
結果如下:
分析: 為什么a.sh中【echo $B】沒有執行,b.sh中【echo $A】沒有執行?
shell是一個腳本程序,對于腳本程序,都是從腳本中一行一行讀取并執行這些命令。因此,第一個【echo $B】沒有執行,顯示為空。第二個b.sh中【echo $A】為 什么也為空,分析如圖所示。
把A、B兩個變量提升為全局變量!會出現什么結果呢?
注意:上圖中,假如把A和B同時提升為“全局變量”,但是子進程b.sh可以使用父進程中的A變量,而父進程a.sh卻不能使用子進程的B變量。
因此在a.sh中可以使用b.sh中的變量B;在b.sh中可以使用a.sh中的變量A。
為了更好地說明上述區別,我們在腳本中分別打印$$,顯示進程數。
// $$:顯示進程數 [root@image_boundary ~]# echo $$ 9544
第一種情況,使用“絕對路徑調用方式”:
第二種情況,使用“內部命令調用方式”:
總結如下:
5、變量中幾個常用符號
反引號``:鍵盤上Tab鍵上方的一個鍵,和~在一個格子上。
操作如下:
[root@bigdata111 ~]# A=`date` [root@bigdata111 ~]# echo $A Mon Sep 30 06:20:02 CST 2019 // $(變量):表示先計算,再賦值; [root@bigdata111 ~]# B=$(date) [root@bigdata111 ~]# echo $B Mon Sep 30 06:20:36 CST 2019 // 練習:你可以嘗試以下以下操作,看看結果是什么? [root@bigdata111 ~]# ll total 8 -rw-r--r--. 1 root root 390 Oct 2 01:04 a.txt -rw-r--r--. 1 root root 0 Oct 2 01:03 b.txt drwxr-xr-x. 2 root root 4096 Oct 2 01:04 study [root@bigdata111 ~]# echo `ll` // 這個結果是什么 [root@bigdata111 ~]# echo $(ll) // 這個結果是什么
${var}:獲取變量本來的值;變量存在,輸出原有值;變量不存在,輸出空。 ${var:-word}:判斷某個變量是否存在。 變量存在且有值,輸出變量var的值; 變量不存在,輸出word。 ${var:+word}:判斷某個變量是否存在。 變量存在且有值,輸出word; 變量不存在,輸出為空。 ${var:=word}:變量存在,返回變量var的值; 變量不存在,相當于創建一個新變量var,并賦值為word。 ${var:?message}:變量存在,輸出變量var的值; 變量不存在,報錯誤。
// 0代表上一次正確執行,正數代表上一次未正確執行; $?表示上一個命令退出的狀態碼; $$ 表示當前進程編號; $0 表示當前腳本名稱; $n 表示n位置的輸入參數(n代表數字,n>=1); $# 表示獲取參數的個數,常用于循環; $*和$@都表示獲取參數列表。
操作如下:
[root@bigdata111 ~]# vim uni_var.sh [root@bigdata111 ~]# cat uni_var.sh #!/bin/bash echo $? #表示上一個命令退出的狀態碼 echo $$ #表示當前的進程編號 echo $0 #表示當前的腳本名稱 echo $1 #表示第1個位置參數 echo $2 #表示第2個位置參數 echo $3 #表示第3個位置參數 echo $# #表示參數的個數 echo $@ #輸出參數列表 echo $* #輸出參數列表 [root@bigdata111 ~]# sh uni_var.sh aa bb cc 0 4192 uni_var.sh aa bb cc 3 aa bb cc aa bb cc
$*和$@都表示輸出參數列表,區別如下:
操作如下:
結果如下:
Linux Shell
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。