1. 程式人生 > >【Shell程式設計】變數詳解

【Shell程式設計】變數詳解

一、什麼是變數

在我們上學時,我們就接觸資料方程式;例如:已知x=1 y=x+1 那麼y等於多少,我們毫不猶豫的會算出來2,但是在shell中x就是變數名,那麼對應的1就是變數值,在這裡的等於號,在shell中稱為賦值!
x=1      x(變數名)   =(賦值)    1(變數值)

例如:以下在centos7中展示

[[email protected] ~]# name="yankerp"   <--定義變數-變數名為name,對應的變數值名字叫做yankerp
[[email protected] ~]# echo $name	 <--列印變數值使用echo $變數名
yankerp                          <--輸出結果

以上例子就是一個自定義變數
變數賦值方式;先寫變數名稱,緊接著就是=號 =號的左右不可以有空格。最後是變數值,通過echo $(變數名) 就可以輸出name變數的值,變數值一般需要加雙引號。

二、變數的型別
變數可以分為兩種型別:環境變數(全域性變數) 普通變數(區域性變數)
環境變數一般使用export內建命令匯出的變數,用於定義shell執行環境,保證shell命令能夠正確執行,shell通過環境變數來確定登入的使用者名稱等資訊,所有的環境變數都是系統的全域性變數。
環境變數可以在命令列中建立,但是當用戶退出命令列時這些變數將會丟失,如果需要永久儲存環境變數,那麼就可以在使用者家目錄下的.bash_profile 或者 .bashrc 按照系統的規範在設定環境變數時所有的環境變數名採用大寫的方式;
例如:我現在要設定一個環境變數如下:

export UUU=yankerp 這種變數不會永久的儲存!! 如果需要永久的儲存上面已經說了在 .bashrc 或者 .bash_profile檔案中設定

那麼我們怎麼看系統的變數呢? 使用set、env、declare命令檢視,以下是env檢視結果

XDG_SESSION_ID=171
HOSTNAME=yankerp
TERM=xterm
SHELL=/bin/bash
HISTSIZE=3000
SSH_CLIENT=183.202.244.122 12158 22
SSH_TTY=/dev/pts/4
USER=root
qq=aaaaaa
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
LANG=en_US.utf8
SHLVL=1
HOME=/root
LOGNAME=root
SSH_CONNECTION=183.202.244.122 12158 10.141.58.170 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
PROMPT_COMMAND=history -a; printf "\033]0;%
[email protected]
%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" XDG_RUNTIME_DIR=/run/user/0 HISTTIMEFORMAT=%F %T _=/usr/bin/env

set env daclare的區別

set命令:輸出全部的變數;
env命令:只輸出全域性變數;
declare命令:輸出全部的變數、函式、整數和已經匯出的變數;
set -o命令:顯示bash shell的所有引數配置資訊;

 

以下是set輸出結果,使用tail檢視set命令輸出的最後5行等...

[[email protected] ~]# set | tail -5
{ 
    local quoted;
    _quote_readline_by_ref "$1" ret;
    printf %s "$ret"
}
[[email protected] ~]# set -o | head -5
allexport       off
braceexpand     on
emacs           on
errexit         off
errtrace        off
[[email protected] ~]# env | tail -5
LESSOPEN=||/usr/bin/lesspipe.sh %s
PROMPT_COMMAND=history -a; printf "\033]0;%[email protected]%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"
XDG_RUNTIME_DIR=/run/user/0
HISTTIMEFORMAT=%F %T 
_=/usr/bin/env

三、自定義環境變數

1、設定環境變數

在設定環境變數之前我們需要使用export命令 具體如下:

export 變數名=tom
export CSDN=yankerp

以下是自定義全域性變數的例項

[[email protected] ~]# tail -1 /etc/profile <----檢視/etc/profile最後一行
export CSDN=yankerp    ---<輸出此行並儲存
[[email protected] ~]# source /etc/profile  <---<使/etc/profile生效
[[email protected] ~]# echo $CSDN     <----在變數前面加上$符號並列印變數值
yankerp              <----輸出結果
[[email protected] ~]# env | grep CSDN   <----使用env檢視環境變數並使用grep過濾CSDN變數值
CSDN=yankerp     ----輸出結果

2、修改登入提示

[[email protected] ~]# cat /etc/motd 
this is a yankerp!!!

登入提示如下:

Last login: Sat Jan 27 23:27:01 2018 from 
this is a yankerp!!!
[[email protected] ~]# 

3、用echo以及printf命令打印出環境變數

[[email protected] ~]# echo $UID
0
[[email protected] ~]# echo $USER
root
[[email protected] ~]# echo $SHELL
/bin/bash
[[email protected] ~]# printf "$HOME\n"
/root

在以上的printf後面加\n是表示換行的意思,printf一般不是經常用,說白了這個命令是為awk打基礎。

使用env或set命令顯示預設的環境變數

[[email protected] ~]# env
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
CSDN=yankerp
PWD=/root
LANG=en_US.utf8
SHLVL=1
HOME=/root
LOGNAME=root
SSH_CONNECTION=183.202.244.122 12120 10.141.58.170 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
PROMPT_COMMAND=history -a; printf "\033]0;%[email protected]%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"
XDG_RUNTIME_DIR=/run/user/0
HISTTIMEFORMAT=%F %T

用set命令顯示環境變數包括區域性變數

[[email protected] ~]# set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_COMPLETION_COMPAT_DIR=/etc/bash_completion.d
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="2" [2]="46" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")

問題來了 怎麼取消變數呢?

例如:我設定一個環境變數

[[email protected] ~]# export YANKAI=ywyankerp
[[email protected] ~]# echo $YANKAI
ywyankerp
[[email protected] ~]# env | grep YANKAI
YANKAI=ywyankerp

現在我們使用unset命令消除變數 如下:

[[email protected] ~]# unset YANKAI
[[email protected] ~]# echo $YANKAI

[[email protected] ~]# 

四、普通變數

1、定義本地變數

本地變數在使用者當前的shell指令碼中使用,如果在shell中開啟另外一個程序或者說退出那麼將會失效

普通變數的型別

變數名=yankerp
變數名='yankerp'
變數名="yankerp"

變數名一般都是由字母、數字、下劃線組成的,變數名不能以數字開頭

變數的內容可以用單引號、雙引號、引起來,同時也可以不加引號,但是這三者的含義是不一樣的。如下:

[[email protected] ~]# a=192.168.1.10
[[email protected] ~]# b='192.168.1.10'
[[email protected] ~]# c="192.168.1.10"
[[email protected] ~]# echo  "a=$a"
a=192.168.1.10
[[email protected] ~]# echo  "b=$b"
b=192.168.1.10
[[email protected] ~]# echo  "c=$c"
c=192.168.1.10
[[email protected] ~]# 

在以上例子中好像看不出來哪裡不一樣,說明了將連續普通的字串的內容賦值給變數,不管用不用引號,只要變數名是什麼,它就會列印什麼

那麼到這裡到底有什麼區別例項證明如下:

例如:我不用''引號設定變數和用''號設定如下:

[[email protected] ~]# a=yan ker p
-bash: ker: command not found
[[email protected] ~]# a='yan ker p'
[[email protected] ~]# echo $a
yan ker p
[[email protected] ~]# 

經過以上例項我們可以看到,不加單引號設定變數,其中變數名有空格,但是它會報錯,如果我們加了單引號,其中變數名有空格,它就會打印出來我們設定的yan ker p;

結論:當我們不加單引號時必須是連續的字串才可以;如果加了''號那麼結論是當變數名寫什麼那麼它就會輸出什麼。

“”號案例如下:

[[email protected] ~]# a='yan ker p'
[[email protected] ~]# b="yan ker p" 
[[email protected] ~]# echo $a
yan ker p
[[email protected] ~]# echo $b
yan ker p
[[email protected] ~]# 

在以上的案例中我們並沒有發現''號於“”號有什麼區別,但是我們來繼續看下面的案例

[[email protected] ~]# a=$("ls") <----此變數名ls為linux命令
[[email protected] ~]# echo $a
anaconda-ks.cfg

總結:""這種定義的方式特點是:輸出變數內容時引號變數及命令會經過解析後在輸出

把一個變數命令賦值的方法

例如:我們要查詢我們的IP地址 我們可以使用ifconfig這個命令來檢視,但是我們如何在shell指令碼中實現呢?

按照很普通的想法是這樣的如下:

在以上指令碼中我們就會認為,IP是變數名,ifconfig是變數值,那麼我們執行這個指令碼echo $IP 那麼就會輸出ip資訊嗎?

[[email protected] Log.sh]# cat test1.sh 
#!/bin/bash
# Sat Jan 27 20:45:40 CST 2018
# User <[email protected]>
# Version 1.1.0
# This is a cs.
IP=ifconfig

[[email protected] Log.sh]# source test1.sh 
[[email protected] Log.sh]# echo $IP
ifconfig
[[email protected] Log.sh]# 

我們發現它輸出的是ifconfig字串,為啥? 因為IP=ifconfig在linux中它會很簡單的認為ifconfig就是個字串並不是命令....

接下來介紹兩個符號

變數名=`ifconfig`
變數名=$("ifconfig")

我們在上面已經說過""的作用,它是輸出變數內容時引號變數及命令會經過解析後在輸出

指令碼內容如下:

[[email protected] Log.sh]# cat test1.sh 
#!/bin/bash
# Sat Jan 27 20:45:40 CST 2018
# User <[email protected]>
# Version 1.1.0
# This is a cs.
IP=$("ifconfig")
[[email protected] Log.sh]# source test1.sh 
[[email protected] Log.sh]# echo $IP
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.141.58.170 netmask 255.255.192.0 broadcast 10.141.63.255 ether 52:54:00:b3:c1:34 txqueuelen 1000 (Ethernet) RX packets 92758 bytes 9588691 (9.1 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 91995 bytes 12612699 (12.0 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

從以上指令碼中我們可以看到ifconfig命令已經生效,我們暫時不用管他的排版

同時我們也可以在命令段的前後加``反撇號 這個看個人習慣 我是習慣用反撇號;偷笑

[[email protected] ~]# IP=`ifconfig`

舉幾個例子``

[[email protected] ~]# SJ=`date +%F`.tar.gz
[[email protected] ~]# echo $SJ
2018-01-28.tar.gz

以上date +%f就是一條命令 在這條命令的基礎上我們加了``反撇號讓它解析同時在後面加了.tar.gz 輸出結果為時間+.tar.gz

再次測試如下:

[[email protected] ~]# YYY=etc_`hostname`.tar.gz
[[email protected] ~]# echo $YYY
etc_yankerp.tar.gz
[[email protected] ~]# echo 'yankerp date +%F'
yankerp date +%F
[[email protected] ~]# echo "yankerp date +%F"
yankerp date +%F
[[email protected] ~]# echo "yankerp `date +%F`"
yankerp 2018-01-28

注意以上的反撇號

案例1:在正則表示式三劍客中grep命令過濾字串給加引號

[[email protected] Log.sh]# cat test   <------文字內容如下:
yankerp
zhangsan
lisi
wangwu
zhouliu
zhouwu
zhousi
CSDN

[[email protected] Log.sh]# aaa=yankerp       <----設定變數aaa=yankerp
[[email protected] Log.sh]# grep $aaa test    
yankerp
[[email protected] Log.sh]# grep '$aaa' test
[[email protected] Log.sh]# grep "$aaa" test
yankerp
[[email protected] Log.sh]# 

案例2:在正則表示式三劍客中awk命令測試

[[email protected] ~]# EEE=123456
[[email protected] ~]# awk 'BEGIN {print "$EEE"}'
$EEE
[[email protected] ~]# awk 'BEGIN {print '$EEE'}'
123456
[[email protected] ~]# awk 'BEGIN {print "'$EEE'"}'
123456
[[email protected] ~]#

我們發現和前面的不一樣啊 不是說""是解析命令嗎 為什麼在awk中它是輸入什麼就輸出什麼呢,而使用''號在之前是輸入什麼就輸出什麼,這就是AWK呼叫shell變數的特殊用法

宣告:以上文章是<<跟著老男孩學Linux運維Shell程式設計實戰>>第三章看完的總結;

好了,本章就結束了,希望對您有所幫助! 再見~~~