Shell编程从入门到精通-第二章.shell变量

二、Shell变量


2.1、什么是变量

在小学的时候我们学过数学方程式,例如:已知x=1,y=x+1那么y等于多少
在上述的题目中x和y被称为未知数,但是在shell编程里它们是变量名,等号右边的1和x+1是变量的内容,(这里“=”被称为赋值)


通过上面的介绍可以得出,变量就是用一个固定的字符串代替更多,更复杂的内容,该内容包含变量、路径、字符串等其他的内容,变量是暂时存储数据的地方和标记,所存储的数据存在内存空间中,通过调用内容空间的变量名字就可以取出变量对应的数据。使用变量最大的好处就是方便,当然,除了方便以外,很多时候在变成中使用变量也是必须的,否则就无法完成开发工作了。

[root@Shell~]#blog=zhang789#创建变量
[root@Shell~]#echo$blog#输出变量zhang789

变量分为两种,环境变量(全局变量)和普通变量(局部变量)

1、环境变量也可以称为全局变量,可以在创建他们的shell及其派生出来的任意子进程shell中使用,环境变量又可以分为用户自定义变量和bash内置的环境变量
2、普通变量也可以称为局部变量,只能在创建它们的shell函数活shell脚本中使用,普通变量一半都是由开发者在开发程序时创建


2.2、环境变量

环境变量用于定义shell的运行环境,保证Shell命令的正确执行,通过环境变量来确定登陆用户名、命令路径、终端类型、登陆目录等,所有的环境变量都是系统全局变量,可用于所有子进程中,这包括编辑器、Shell脚本和各类应用。


环境变量可以在命令行中设置,当用户退出时这些变量值也会丢失,因此最好在用户家目录下的.bash_profile文件中或全局配置/etc/bashrc,/etc/profile文件或者/etc/profile.d/中定义。将环境变量放入上述的文件中,每次用户登陆时这些变量值都将被初始化。
传统上,所有环境变量均为大写。环境变量应用于用户进程前,都应该用export命令导出,例如:export AS=1


环境变量可用在创建他们的shell和从该shell产生的任意子shell或进程中。他们通常被称为全局变量以区别局部变量。通常,环境变量应该大写。环境变量是已经用export内置命令导出的变量。
有一些环境变量,比如HOME、PATH、SHELL、UID、USER等,在用户登陆之前就已经被/bin/login程序设置好了。通常环境变量定义并保存在用户家目录下的.bash_profile文件中。

可以通过一下的命令查看环境变量

1.env(只显示全局变量)
2.set(所有的变量)
3.declare(所有变量,包括函数、整数和已导出的)

环境变量设置的常用文件及区别

1、用户的环境变量配置

[root@Shell~]#ll/root/.bash_profile
-rw-r--r--.1rootroot17612月292013/root/.bash_profile
[root@Shell~]#ll/root/.bashrc
-rw-r--r--.1rootroot17612月292013/root/.bashrc

2、全局环境变量的配置

[root@Shell~]#ll/etc/profile
-rw-r--r--.1rootroot17506月72013/etc/profile
[root@Shell~]#ll/etc/bashrc
-rw-r--r--.1rootroot28358月122015/etc/bashrc

用户登陆后加载的内容,可以在跳板机上操作,让每切换一次用户显示当前登陆的USER and IP切换或者登陆用户提示信息

[root@Shell~]#cd/etc/profile.d/
[root@Shellprofile.d]#cathello.sh
echo"HelloZhanghe"
echo"Blog:zhang789.blog.51cto.com"
#退出重新登录下
root@192.168.102.161'spassword:
Lastlogin:FriJun917:32:132017from192.168.102.1
HelloZhanghe#我们输出的信息
Blog:zhang789.blog.51cto.com#作者的博客地址
[root@Shell~]#

用户第一次登陆时提示,只能是字符串

Lastlogin:ThuApr212:15:212015from10.0.0.122welcometoUbuntulinuxtraining!
$cat/etc/motd
welcometoUbuntulinuxtraining!

2.3、定义全局变量


[root@Shell~]#exportBLOG_NAME='zhang789.blog.51cto.com'
[root@Shell~]#echo$BLOG_NAME
zhang789.blog.51cto.com
[root@Shell~]#ZABBIX=3.2
[root@Shell~]#exportZABBIX
[root@Shell~]#env|grepZABBIX
ZABBIX=3.2
[root@Shell~]#env|grepBLOG_NAME
BLOG_NAME=zhang789.blog.51cto.com
[root@Shell~]#exportLANG=EN#更改语言的环境变量
[root@Shell~]#declare-xNAME=zhanghe

2.3.1、显示与取消环境变量

设置与取消环境变量
[root@Shell~]#exportBlog=zhang789
[root@Shell~]#echo$Blogzhang789
[root@Shell~]#unsetBlog
[root@Shell~]#echo$Blog
[root@Shell~]#
[root@Shell~]#unsetBLOG_NAME
[root@Shell~]#env|grepBLOG_NAME
[root@Shell~]#

常见系统环境变量

wKioL1k_TPihUJXCAAJuI-6bxyA434.png

2.3.2、环境变量初始化与对应文件的生效顺序

登录Linux系统并启动一个bash shell时,默认情况下bash会在若干个文件中查找环境变量的设置,这些文件可统称为系统环境文件,bash检查的环境变量文件的情况取决系统运行shell的方式,系统运行shell的方式一般有3种
1、 通过系统用户登录后默认运行的sell
2、 非登录交互式运行的shell
3、 执行脚本运行的非交互式shel

登录加载顺序

1、系统登录系统后会首先加载/etc/profile全局环境变量文件,这是Linux系统上面默认的shell主环境变量文件,系统上面每个登录用户都会加载这个文件
2、当加载完/etc/profile文件后,才会执行/etc/profile.d目录下的脚本文件,这个目录下的脚本文件有很多,例如:系统的字符集设置(/etc/sysconfig/i18n)等。
3、后面开始运行$HOME/.bash_profile(用户环境变量文件),在这个文件中,又会去找$HOME/.bashrc(用户环境变量文件),如果有,则执行,如果没有,则不执行,在$HOME/.bashrc文件中又会去找/etc/bashrc(全局环境变量文件)如果有,则执行,如果没有,则不执行

如果用户的shell不是登录启动的(比如敲bash或者其他不输入用户名密码登录及远程SSH连接情况)这种只会加载$HOME/.bashrc(用户环境变量文件)并找/etc/bashrc(全局环境变量文件

2.4、定义本地变量

本地变量在用户当前的Shell生存期额脚本中使用。例如,本地变量Blog取值为zhang789,这个值只在用户当前Shell生存期中有意义,如果在shell中启动另一个进程或退出,本地变量Blog值无效。

普通字符串变量定义:

变量名=value
变量名='value'
变量名="value"命令变量定义
变量名=$()
变量名=``

shell中变量明的要求
一般是由字母,数字,下划线组成,以字母开头
例1

[root@Shell~]#a=192.168.1.1
[root@Shell~]#b='192.168.1.1'
[root@Shell~]#c="192.168.1.1"
[root@Shell~]#echo"a=$a"a=192.168.1.1
[root@Shell~]#echo"b=$b"b=192.168.1.1
[root@Shell~]#echo"c=${c}"c=192.168.1.1

例2

[root@Shell~]#a=192.168.1.2-$a
[root@Shell~]#b='192.168.1.2-$a'
[root@Shell~]#c="192.168.1.2-$a"
[root@Shell~]#echo"a=$a"a=192.168.1.2-192.168.1.1
[root@Shell~]#echo"b=$b"b=192.168.1.2-$a
[root@Shell~]#echo"c=${c}"c=192.168.1.2-192.168.1.2-192.168.1.1

提示

  1. 第一种定义a变量的方式是直接指定变量内容内容一般为简单连续的数字、字符串、路径明等。

  2. 第二种定义b变量的方式是通过单引号定义变量。这个方式会 的特点是:输出变量时引号里是什么就输出什么,即使内容中有变量也会把变量原样输出,此方法比较适合定义显示纯字符串。

  3. 第三种定义c变量方式是通过双引号定义变量。这个方式的特点是:输出变量时引号里的变量会经过解析后输出该变量内容。而不是把引号中变量名元杨树称呼,适合于字符串中附带有变量的内容的定义。

  4. 习惯:数字不加引号,其他默认加双引号

2.5、定义变量单引号、双引号于不加引号

有关单引号、双引号与不加引号的简要说明如下:

wKiom1k_UGeSvteJAAPSaknFYas893.png

范例

[root@Shell~]#echo'todayisdate'
todayisdate#单引号看到什么就输出什么
[root@Shell~]#echo'todayis`date`'
todayis`date`#单引号看到什么就输出什么
[root@Shell~]#echo"todayisdate"
todayisdate#双引号时如果里面是变量,会先把变量解析成具体内容显示
[root@Shell~]#echo"todayis`date`"
todayisWedApr115:46:18CST2015#双引号时如果里面是变量,会先把变量解析成具体内容显示
[root@Shell~]#echo"todayis$(date)"
todayisWedApr115:46:24CST2015#双引号时如果里面是变量,会先把变量解析成具体内容显示
#对于连续的字符串等内容一般不加引号也可,加双引号一般比较保险,推荐。

变量定义后,调用时测试

[root@Shell~]#Blog=zhang789#-->创建一个不带引号的变量
[root@Shell~]#echo$Blog#-->不加引号,显示一个变量解析后的内容
zhang789
[root@Shell~]#echo'$Blog'#-->单引号,显示一个变量本身
$Blog
[root@Shell~]#echo"$Blog"#-->双引号,显示一个变量内容,引号内可以是变量、字符串等
zhang789
[root@Shell~]#ETT=123
[root@Shell~]#awk'BEGIN{print"$ETT"}'
$ETT
[root@Shell~]#awk"BEGIN{print"$ETT"}"
123
[root@Shell~]#awk'BEGIN{print'$ETT'}'
123

自定义普通字符串变量的建议

1、内容时纯数字(不带空格),定义方式可以不加引号(单或双)

ZHANG=33
HE=yes

2、没特殊情况,字符串一般用双引号定义,特别是多个字符串中间有空格时

NFSD_MODULE=”noload”MyNAME=”ZHANGisahandsomeboy.”

3、变量内容需要原样输出时,要用单引号(“) 例如:

BLOG_NAME=’ZHANG’


2.7、变量的命名规范

  1. 变量命名要统一,使用全部大写字母,语句要清晰,能够正确表达变量内容的含义,过长的英文单词可采用前几个字符代替,多个单词连接使用_号链接,引用时,最好以加大括号或{APACHE_ERR_NUM}”外面加双引号方式引用变量。

  2. 避免无意义字符或数字:例如下面的COUNT,并不知道其确切含义;

范例:COUNT的不确切定义

CONUT=`grepkeywordsfile`
if[${CONUT}-ne22]
thenecho“DoSomething”
fi

全局变量和局部变量命名

1、脚本中的全局变量定义,如ZHANG_HOME或ZHANGHOME,在变量使用时使用{ }将变量括起或”{ZHANG_HOME}”
范例:操作系统函数库脚本内容全局变量截取例子

$cat/etc/init.d/functions

2、脚本中局部变量定义:存在于脚本函数(function)中的变量称为局部变量,要以local方式进行声明,使只只在本函数作用域内有效,防止变量在函数中的命名与变量外部程序中变量重名造成异常.

2.1、函数中的变量定义
checkpid(){
locali
foriin$*;do
[-d"/proc/$i"]&&return0
done
return1
}
2.2、变量合并

当某些变量或配置项要组合起来才有意义时,如文件的路径和文件名称,建议将要组合的变量合并到一起赋值给一个新的变量,这样既方便之后的调用,也为以后进行修改提供了方便。

范例:自动化安装httpd的脚本变量合并定义

VERSION="2.2.22"
SOFTWARE_NAME="httpd"
SOFTWARE_FULLNAME="${SOFTWARE_NAME}-${VERSION}.tar.gz"
2.3、变量定义总结:多学习模仿操作系统自带的/etc/init.d/function函数库脚本的定义思路。
  1. 1、变量名只能为字母,数字,下划线,字母开头。

  2. 2、规范的变量名定义方法:见名只意
    a) ZHANGEAge=1 每个单词的首字母大写
    b) ZHANGE_age=1 单词之间用”_”
    c) ZHANGEAgeSex=1 驼峰语法:首个单词的首字母小写,其余单词首字母大写

  3. 3、=号的知识,a=1等号是赋值的意思

  4. 4、比较是不是相等,为==打印变量,变量名前接$符号,变量名后面紧接着字符的时候,要用大括号括起来

  5. 5、注意变量内容引用方法,一般用引号,简单连续字符串可以不加引号,希望原样输出,使用单引号。

  6. 6、变量内容是命令,这个时候要用反引号或者$()把变量括起来使用。

2.8、特殊变量

2.8.1、位置变量

在shell中存在一些特殊且重要的变量,例如:$1,$#,我们称之为特殊位置变量,要从命令行、函数或脚本执行的时候传递参数

wKioL1k_VCCR-AP6AANRntQOMhg208.png

判断参数的个数
$cattejing4.sh
[$#-ne2]&&{
echo"musetwo"
exit1
}
echo$1$2

第二个脚本

$cattejing5.sh
#no1
if[$#-ne2]
then
echo"USAGE:/bin/sh$0arg1arg2"
exit1
fi
#no2
echo$1$2

控制用户传参个数

$cata.sh
#!/bin/bash
[$#-ne2]&&{
echo"musetwo"
exit1
}
echozhang789
$sha.shsa
musetwo
$sha.shsaha
zhang789

*和@的区别例子

  1. 将所有的命令行所有参数视为单个字符串,等同于13,$*;

  2. 将命令行每个参数视为单独的字符串,等同于13。这是将参数传递给其他程序的最佳方式,因为他会保留所有内嵌在每个参数里的任何空白。

上述区别仅在于双引号的时候,即和@.

$set--"Iam"handsomeansheng.#传入三个参数$echo$##现在有三个参数3
$foriin"$*";doecho$i;done#在有双引号的情况下,参数里因好内内容当作一个参数输出了,这才真正符号我们传入的参数需求,set--"Iam"
handsomeansheng.Iamhandsomeansheng.
$foriin"$@";doecho$i;done#在有双引号的情况下,每个参数独立输出
Iam
handsome
ansheng.
$fori;doecho$i;done#去掉in变量列表,相当于in“$@”
Iam
handsome
ansheng.
$foriin$*;doecho$i;done#不加双引号,把所有参数输出,然后第一个参数“Iam”也拆开输出了.
$foriin$@;doecho$i;done#不加双引号,把所有参数输出,然后第一个参数“Iam”也拆开输出了.

2.8.2、进程状态变量

wKioL1k_VP3wCcdZAAF2Q2qV9rY789.png

通过脚本控制错误返回值
[root@Shell~]#catfanhui.sh
exit100
[root@Shell~]#shfanhui.sh
[root@Shell~]#echo$?
100
$$案例应用案例:当系统中只能有某个脚本同时只能运行一个进程的时候。
#!/bin/shpidpath=/tmp/a.pid
if[-f"$pidpath"]
then
kill-USR2`cat$pidpath`>/dev/null2>&1
rm-f$pidpath
fi
echo$$>$pidpath
sleep300
$_
[root@Shell~]#/etc/init.d/ntpdstart
Startingntpd:[OK]
[root@Shell~]#echo$_
start

2.9、shell变量子串

常用操作如下表:man bash找本节资料“Parameter Expansion”

${#string}返回$string的长度
${string:position}在$string中,从位置$position之后开始提取子串
${string:position:length}在$string中,从位置$position之后开始提取长度为$length的子串
${string#substring}从变量$string开头开始删除最短匹配$substring子串
${string##substring}从变量$string开头开始删除最长匹配$substring子串
${string%substring}从变量$string结尾开始删除最短匹配$substring子串
${string%%substring}从变量$string结尾开始删除最长匹配$substring子串
${parameter/pattern/string}使用string,来代替第一个匹配的pattern
${parameter/#pattern/string}从开头匹配string变量中的pattern,使用string来替换匹配的pettern
${parameter/%patter/string}从结尾开始匹配string变量中的pattern,就用string来替换匹配pattern
${parameter//pattern/string}使用string,来代替所有匹配的pattern更多资料manbansh查找“ParameterExpansion”

2.9.1、${#string}获取变量字符串的长度

[root@Shell~]#OLDBOY="Iamoldboy"
[root@Shell~]#echo$OLDBOYIamoldboy
[root@Shell~]#echo$OLDBOY|wc-L11
[root@Shell~]#echo${#OLDBOY}11
[root@Shell~]#exprlength"$OLDBOY"11

2.9.2、输出整个字符串的一部分

[root@Shell~]#{string:position}
[root@Shell~]#ansheng="Iamansheng"
[root@Shell~]#echo${ansheng:2}
[root@Shell~]#{string:position:length}
amansheng
[root@Shell~]#echo${ansheng:2:2}
am

2.9.3、##

[root@Shell~]#echo${ansheng#a*c}
ABC123ABCabc
[root@Shell~]#echo$ansheng
abcABC123ABCabc
[root@Shell~]#echo${ansheng##a*c}

2.9.4、%%

[root@Shell~]#echo$ansheng
abcABC123ABCabc
[root@Shell~]#echo${ansheng%a*c}
abcABC123ABC
[root@Shell~]#echo${ansheng%%a*c}
[root@Shell~]#echo${ansheng%C*bc}
abcABC123AB
[root@Shell~]#echo${ansheng%%C*bc}
abcAB

2.9.5、/替换

[root@Shell~]#ansheng=abcABC123ABCabc
[root@Shell~]#echo$ansheng
abcABC123ABCabc
[root@Shell~]#echo${ansheng/abc/ansheng}
anshengABC123ABCabc
[root@Shell~]#echo${ansheng/#abc/ansheng}
anshengABC123ABCabc
[root@Shell~]#echo${ansheng/%abc/ansheng}
abcABC123ABCansheng

案例:批量改名

[root@Shell~]#f=stu_102999_5_finished.jpg
[root@Shell~]#echo$f
stu_102999_5_finished.jpg
[root@Shell~]#echo${f/_finished/}
stu_102999_5.jpg
[root@Shell~]#f=stu_102999_5_finished.jpg
[root@Shell~]#echo${f/_finished/}
stu_102999_5.jpg
[root@Shell~]#mv$f`echo${f/_finished/}`
[root@Shell~]#ls-lrt|tail-5
-rw-r--r--1rootroot04月216:59stu_102999_5.jpg
-rw-r--r--1rootroot04月216:59stu_102999_4_finished.jpg
-rw-r--r--1rootroot04月216:59stu_102999_3_finished.jpg
-rw-r--r--1rootroot04月216:59stu_102999_2_finished.jpg
-rw-r--r--1rootroot04月216:59stu_102999_1_finished.jpg
[root@Shell~]#forfin`ls*fin*.jpg`;domv$f`echo${f/_finished/}`;done
[root@Shell~]#ls-lrt|tail-5
-rw-r--r--1rootroot04月216:59stu_102999_5.jpg
-rw-r--r--1rootroot04月216:59stu_102999_4.jpg
-rw-r--r--1rootroot04月216:59stu_102999_3.jpg
-rw-r--r--1rootroot04月216:59stu_102999_2.jpg
-rw-r--r--1rootroot04月216:59stu_102999_1.jpg

小结:

#是开头删除匹配最短
##是开头删除匹配最长
%是结尾删除匹配最短
%%是结尾删除匹配最长

相关文章

普通模式 >G 增加当前行到文档末尾处的缩紧层级 $ 移动到本行的末尾 . 相当于一个...
原文连接: https://spacevim.org/cn/layers/lang/elixir/ 模块简介 功能特性 启用模块 快捷键 语言专属...
原文连接: https://spacevim.org/cn/layers/lang/dart/ 模块简介 功能特性 依赖安装及启用模块 启用模...
 =   赋值操作符,可以用于算术和字符串赋值 +        加法计算     -        减法运算...
1.根据包名来查看指定的APP指定数据 adb shell "top | grep com.xxx.xxx" 由于这样打印出来的数...
ctrl+F 向下翻页 ctrl+B 向下翻页 u 取消最近一次操作 U 取消当前行的操作 ZZ 保存当前内容并退出 gg 跳...