Shell 变量基础知识变量是暂时存储数据的地方及数据标记所存储的数据存在于内存空间中通过正确地调用内存空间中变量的名字就可以取出与变量对应的数据。变量的内容一般要加双引号以防止出错特别是当值里的内容之间有空格时。# 赋值变量变量名xxx[rootlocalhost ~18:56:59]# name123456# 加$[rootlocalhost ~18:58:49]# echo $name123456变量类型变量根据范围可分为两类全局变量在创建它们的 Shell及其派生出来的任意子进程 Shell 中使用。局部变量只能在创建它们的 Shell 函数或 Shell 脚本中使用。变量根据是否是用户自定义也可分为两类普通变量也称为常规变量由开发者在开发脚本程序时创建。环境变量定义shell 执行环境。环境变量又可分为自定义环境变量和bash内置的环境变量。环境变量环境变量一般是指用export内置命令导出的变量用于定义 Shell 的运行环境保证 Shell 命令的正确执行。Shell 通过环境变量来确定登录用户名、命令路径、终端类型、登录目录等所有的环境变量都是系统全局变量可用于所有子进程中这包括编辑器、 Shell 脚本和各类应用。环境变量可以在命令行中设置和创建但用户退出命令行时这些变量值就会丢失因此如果希望永久保存环境变量可在用户家目录下的.bash_profile或.bashrc(非用户登录模式特有例如远程SSH)文件中或者全局配置/etc/bashrc(非用户登录模式特有例如远程SSH)或/etc/profile文件中定义。在将环境变量放入上述的文件中后每次用户登录时这些变量都将被初始化。按照系统规范所有环境变量的名字均采用大写形式。在将环境变量应用于用户进程程序之前都应该用export命令导出定义。有一些环境变量比如HOME、PATH、USER等在用户登录之前就已经被/bin/login程序设置好了。通常环境变量被定义并保存在用户家目录下的.bash_profile文件或全局的配置文件/etc/profile中。部分bash环境变量展示EDITOR默认编辑器。HISTFILE历史文件位置。HISTSIZE历史命令个数。HISTTIMEFORMAThistory历史命令显示格式。PS1命令行提示符。LANGShell 环境语言。PATH命令搜素路径。HOME当前用户家目录。USER当前用户的用户名。UID当前用户的用户ID。PWD当前 Shell 路径。IFS字符串分隔符。在查看设置的变量时有3个命令可以显示变量的值set 命令输出所有的变量包括全局变量和局部变量。env 命令只显示全局变量包括 shell 的环境。declare 命令输出所有的变量、函数、整数和已经导出的变量。set -o命令显示bash Shell 的所有参数配置信息。设置环境变量1. 设置环境变量如果想要设置环境变量就要在给变量赋值( value )之后或在设置变量时使用export命令具体设置见下文的示例。其实除了export命令带-x选项的declare内置命令也可以完成同样的功能注意此处不要在变量名前面加$。export命令和declare命令的格式如下export 变量名value变量名value ; export 变量名declare -x 变量名value示例exportNAMEcsrdeclare-xNAMEcsrNAMEcsr;exportNAME下面来看看让环境变量永久生效的常用设置文件。用户的环境变量配置文件~/.bash_profile和~/.bashrc。推荐在~/.bashrc文件中设置。全局环境变量的配置文件/etc/profile、/etc/bashrc、/etc/profile.d/。**推荐在 /etc/bashrc 文件中设置。**若要在登录后初始化或显示加载内容则把脚本文件放在/etc/profile.d/下即可无须加执行权限)。2. 设置登录后提示信息第一种是在/etc/motd里增加提示的字符串如下[rootlocalhost ~20:53:49]# vim /etc/motdwelcome to csr linux Shell training.登录后第二种是在 /etc/profile.d/ 下面增加如下脚本。[rootlocalhost ~ 20:57:39]# vim /etc/profile.d/csr.sh echo welcome to csr linux Shell training.补充登录前提示符由文件 /etc/issue 提供。上一次登录记录由ssh服务提供在/etc/ssh/sshd_config文件中配置PrintLastLog yes默认启用。显示与取消环境变量用echo或printf命令打印环境变量。用env或set显示默认的环境变量。用unset消除本地变量和环境变量。环境变量小结变量名通常要大写。变量可以在自身的 Shell 及子 Shell 中使用。常用export来定义环境变量。执行env默认可以显示所有的环境变量名称及对应的值。输出时用$变量名取消时用unset变量名。书写crond定时任务时要注意脚本要用到的环境变量最好先在所执行的 Shell 脚本中重新定义。如果希望环境变量永久生效则可以将其放在用户环境变量文件或全局环境变量文件里。普通变量定义变量名一般是由字母、 数字 、下划线组成的不能以数字开头变量值可以用单引号或双引号引起来也可不加引号但是这三者的含义是不同的。把命令的结果作为变量的内容赋值**变量名(command)∗∗把命令用∗∗(command)** 把命令用**(command)∗∗把命令用∗∗()**括起来生产场景中把命令的结果作为变量的内容进行赋值的方法在脚本开发时很常见。Shell 变量进阶知识Shell 中特殊变量Shell 位置参数变量在 Shell 中存在一些特殊且重要的变量例如$0、$1我们称之为位置参数变量。要从命令行、函数或脚本执行等处传递参数时就需要在 Shell 脚本中使用位置参数变量。部分位置参数变量如下$0获取当前执行的Shell 脚本的文件名如果执行脚本包含了路径那么就包括脚本路径。**n∗∗获取当前执行的Shell脚本的∗∗第n个参数值∗∗。如果n大于9则用大括号括起来例如n**获取当前执行的 Shell 脚本的**第n个参数值**。如果n大于9则用大括号括起来例如n∗∗获取当前执行的Shell脚本的∗∗第n个参数值∗∗。如果n大于9则用大括号括起来例如{10}接的参数以空格隔开。$#获取当前执行的 Shell 脚本后面接的参数数量。**∗∗∗获取当前Shell脚本所有传参的参数不加引号和‘***获取当前 Shell 脚本所有传参的参数不加引号和∗∗∗获取当前Shell脚本所有传参的参数不加引号和‘相同如果给∗‘加上双引号例如‘*加上双引号例如∗‘加上双引号例如‘*则表示将所有的参数视为单个字符串相当于$1 $2 $3。**∗∗获取当前Shell脚本所有传参的参数不加引号和**获取当前 Shell 脚本所有传参的参数不加引号和∗∗获取当前Shell脚本所有传参的参数不加引号和*相同如果给加上双引号例如‘加上双引号例如加上双引号例如‘则表示将所有的参数视为不同的独立字符串相当于$1、“$2”、“$3”…这是将多参数传递给其他程序的最佳方式因为它会保留所有的内嵌在每个参数里的任何空白。[rootlocalhost ~10:49:43]# vim showargs.sh#!/bin/bashecho$0echo$1echo$2echo$10echo${10}echo$#echo$*echo$*echo$echo$[rootlocalhost ~10:59:18]# bash showargs.sh {a..z}showargs.sh a b a0 j26a b c d e f g h i j k l m n o p q r s t uvw x y z a b c d e f g h i j k l m n o p q r s t uvw x y z a b c d e f g h i j k l m n o p q r s t uvw x y z a b c d e f g h i j k l m n o p q r s t uvw x y zShell 进程中的特殊状态变量$?作用获取执行上一个指令的执行状态返回值0为成功非零为失败这个变量最常用。[rootlocalhost ~11:22:22]# ll[rootlocalhost ~11:23:04]# echo $?0Shell 内置变量命令bash Shell 包含一些内置命令。 这些内置命令在目录列表里是看不见的它们由 Shell 本身提供。常用的内部命令有echo、eval、exec、read、shift等。echoecho命令参数选项-n不换行输出内容。-e解析转义字符见下面的字符转义字符:\n换行。\t制表符tab)。\b退格。\r回到行首。[rootlocalhost ~14:36:18]# echo -n CSR;echo csrCSRcsr[rootlocalhost ~15:03:59]# echo -e CSR \n csrCSR csr[rootlocalhost ~15:08:09]# echo -e CSR \ncsrCSR csr[rootlocalhost ~15:16:30]# echo -e CSR\tcsrCSR csr[rootlocalhost ~15:27:50]# echo -ne 123\b;echo haha12haha[rootlocalhost ~15:32:09]# echo -e CSR\rhahahahaeval当 Shell 程序执行到 eval 语句时 Shell 读入参数args并将它们组合成一个新的命令然后执行。[CSRlocalhost ~11:00:14]$vimnoeval.sh[CSRlocalhost ~11:01:20]$bashnoeval.sh hello$1[CSRlocalhost ~11:02:03]$bashnoeval.sh hello world$2[CSRlocalhost ~11:02:09]$vimeval.shevalecho \$$#[CSRlocalhost ~11:10:02]$basheval.sh hello world world[CSRlocalhost ~11:12:10]$basheval.sh hello haha nihao it itread从标准输入读取字符串等信息 传给 Shell 程序内部定义的变量。[rootlocalhost ~15:40:37]# vim read.sh#!/bin/bashread-p输入你想要说的话strecho你想说的话是$str[rootlocalhost ~16:44:30]# bash read.sh输入你想要说的话hello 你想说的话是hello# 静默输入[rootlocalhost ~16:58:53]# read -s -p 请设置用户密码 password请设置用户密码[rootlocalhost ~17:09:39]# echo $password123开发脚本password实现类似passwd工具更改密码。[rootlocalhost ~17:57:03]# vim scr_password#!/bin/bashecho更改用户$1的密码read-sp新的密码password1echoread-sp重新输入新的密码password2echoecho$password1|passwd--stdin$1[rootlocalhost ~17:57:28]# bash ./scr_password CSR更改用户 CSR 的密码 新的密码 重新输入新的密码 Changing passwordforuser CSR. passwd: all authentication tokens updated successfully.execexec 命令能够在不创建新的子进程的前提下 转去执行指定的命令 当指定的命令执行完毕后 该进程 也就是最初的 Shell ) 就终止了。[CSRlocalhost ~10:24:51]$sudo-i[rootlocalhost ~10:25:31]# psPID TTY TIME CMD1609pts/0 00:00:00bash1690pts/0 00:00:00su1719pts/0 00:00:00su1720pts/0 00:00:00bash1733pts/0 00:00:00ps[rootlocalhost ~10:25:35]# exec sleep 10You have new mailin/var/spool/mail/root# sleep命令运行完成后自动返回到原先普通用户shell了。[CSRlocalhost ~10:26:38]$shift[CSRlocalhost ~11:33:21]$vimshift.sh#!/bin/bashecho$1shiftecho$1[CSRlocalhost ~11:44:04]$bashshift.sh1234512变量的数值计算实践算术运算符如果要执行算术运算就会离不开各种运算符号和其他编程语言类似Shell 也有很多算术运算符。下面就给大家介绍一下常见的 Shell 算术运算符、-一元正号和负号。、-加法和减法。*、/、乘法、除法、取余取模。**幂运算。、–增加及减少可前置也可放在变量结尾。!、、||逻辑非取反)、逻辑与and)、逻辑或or)。、、、比较符号小于、小于等于、大于、大于等于。、!、比较符号相等、不相等对于字符串也可以表示相当于。、向左移位、向右移位。~、|、、^按位取反、按位异或、按位与、按位。、、-、*、/、%赋值运算符例如a1相当于aa1a-1相当于aa-1。Shell 中常见的算术运算命令(())用于整数运算的常用运算符效率很高。let用于整数运算类似于(())。expr可用于整数运算但还有很多其他的额外功能。bcLinux下的一个计算器程序适合整数及小数运算。$[]用于整数运算。awkawk 既可以用于整数运算也可以用于小数运算。declare定义变量值和属性-i参数可以用于定义整形变量做运算。(()) 双小括号数值运算命令双小括号 (()) 的作用是进行数值运算与数值比较它的效率很高用法灵活是企业场景运维人员经常采用的运算操作符。5.2.1 (()) 双小括号数值运算的基础语法双小括号 (()) 的操作方法((ii1))此种书写方法为运算后赋值法即将i1的运算结果赋值给变量i。注意不能用echo ((iil))输出表达式的值可以用echo $((iil))输出其值。**i((i1))∗∗可以在‘(())‘前加‘((i1))**可以在 (()) 前加 ((i1))∗∗可以在‘(())‘前加‘ 符表示将表达式运算后赋值给i。(( 87 55))可以进行比较操作还可以加入逻辑与和逻辑或用于条件判断。**echo((21))∗∗需要直接输出运算表达式的运算结果时可以在‘(())‘前加‘((21))**需要直接输出运算表达式的运算结果时可以在 (()) 前加 ((21))∗∗需要直接输出运算表达式的运算结果时可以在‘(())‘前加‘ 符。(()) 双小括号数运算实践示例1[CSRlocalhost ~13:49:25]$echo$((6*3))18[CSRlocalhost ~13:59:25]$a3[CSRlocalhost ~13:59:32]$b8[CSRlocalhost ~13:59:36]$echo$((a*b))24示例2[CSRlocalhost ~14:09:14]$echo$((a23**2-4%3))10[CSRlocalhost ~14:11:46]$a$((100*(1001)/2))[CSRlocalhost ~14:27:44]$echo$a5050特殊运算符# 特殊运算符[CSRlocalhost ~14:35:27]$a11;echo$((a1))12# 比较和判断[CSRlocalhost ~14:35:50]$((15))[CSRlocalhost ~14:36:57]$echo$?1比较和判断# 执行 echo $((a)) 和 echo $((a--)) 命令输出整个表达式时输出的值即为 a 的值表达式执行完毕后会对a进行、--的运算[CSRlocalhost ~15:20:29]$a10[CSRlocalhost ~15:20:38]$echo$((a))10[CSRlocalhost ~15:21:23]$echo$((a))11[CSRlocalhost ~15:22:42]$echo$((a))12# 执行 echo $((a)) 和 echo $((--a)) 命令输出整个表达式时会先对a进行、--的运算然后再输出表达式的值即为a运算后的值。[CSRlocalhost ~15:22:45]$echo$((--a))12[CSRlocalhost ~15:23:23]$echo$((--a))11通过 (())运算后赋值给变量[CSRlocalhost ~15:30:07]$num99[CSRlocalhost ~15:31:00]$echonum$((num1))num100let 命令let运算命令的语法格式为let 表达式let表达式的功能等同于((表达式))[CSRlocalhost ~16:58:31]$i2[CSRlocalhost ~16:58:46]$echo$((i2))4[CSRlocalhost ~16:59:43]$leti8[CSRlocalhost ~17:03:35]$echo$i12expr 命令命令既可以用于整数运算也可以用于相关字符串长度、匹配等的运算处理。expr 命令的基本用法示例[CSRlocalhost ~17:17:06]$expr2222[CSRlocalhost ~17:17:14]$expr224[CSRlocalhost ~17:17:27]$expr2\*24[CSRlocalhost ~17:18:18]$expr2*22*2[CSRlocalhost ~17:19:00]$expr2*2expr: syntax error在使用expr时运算符及用于计算的数字左右都至少有一个空格否则会报错。使用乘号时必须用反斜线屏蔽其特定含义因为 Shell 可能会误解星号的含义。expr 的企业级实战案例详解例1# 计算字符串的长度[CSRlocalhost ~17:51:26]$strabc123[CSRlocalhost ~17:53:14]$exprlength$str6例2# 打印下面语句中字符数不大于6 的单词[CSRlocalhost ~17:54:02]$vimscr.sh#!/bin/bashstringsThis world is the scriptforwordin$stringsdoif[$(exprlength$word)-le6];thenecho$wordfidone[CSRlocalhost ~18:08:09]$bashscr.sh This world is the scriptbc 命令bc是UNIX/Linux下的计算器因此除了可以作为计算器来使用还可以作为命令行计算工具使用。[CSRlocalhost ~20:43:12]$bcbc1.06.95 Copyright1991-1994,1997,1998,2000,2004,2006Free Software Foundation, Inc. This isfreesoftware with ABSOLUTELY NO WARRANTY. For detailstypewarranty. 2^3 8 scale4 2/3 .6666 qui [CSRlocalhost ~ 20:47:04]$ echo scale4;2/3|bc.6666awk 命令实现计算适合小数和整数特别是命令行计算尤其是小数运算很精确好用。[CSRlocalhost ~21:22:02]$echo3.58.8|awk{ print $1-$2 }-5.3Shell 脚本的条件测试条件测试方法综述执行条件判断表达式后通常会返回真或假就像执行命令后的返回值为0表示真非0表示假。在 bash 编程里条件测试常用的语法如下语法1test 判断表达式test命令和判断表达式之间至少有一个空格。语法2[ 判断表达式 ]和test命令的用法相同这是推荐方法。[]的边界和内容之间至少有一个空格。语法3[[ 判断表达式 ]]是比test和[]更新的语法格式。[[]]的边界和内容之间至少有一个空格。语法4(( 判断表达式 ))一般用于 if 语句。(())(双小括号两端不需要有空格。语法5comand命令的返回值确定表达式的真值或假值。有几个注意事项需要说明一下:语法1中的test命令和语法2中的[]是等价的语法3中的[[]]为扩展的test命令语法4中的(())常用于计算。建议使用相对友好的语法2即中括号[]的语法格式。在[[ ]]双中括号中可以使用通配符等进行模式匹配这是其区别于其他几种语法格式的地方。、||、、等操作符可以应用于[[]]中但不能应用于[]中在[]中一般用-a、-o、-gt(用于整数)、-lt(用于整数代替上述操作符。对于整数的关系运算也可以使用 Shell 的算术运算符(())。test 条件测试的简单语法及示例test条件测试的语法格式为test 判断表达式# 判断文件是否存在[rootlocalhost ~17:30:37]# test -f script echo 文件存在 || echo 文件不存在文件存在该语句表示如果file文件存在则输出true否则输出false。这里的是逻辑与||是逻辑或。test的-f参数用于测试文件是否为普通文件test命令若执行成功为真)则执行后面的命令而||后面的命令是test命令执行失败之后为假所执行的命令。另外逻辑操作符和||的两端既可以有空格也可以无空格。带空格看起来会更美观一些建议使用带空格的格式。[]中括号条件测试语法及示例[]条件测试的语法格式为[ 判断表达式 ]⚠️ 中括号内部的两端要有空格[]和test等价即test的所有判断选项都可以直接在[]里使用。# 判断文件是否存在[rootlocalhost ~18:25:15]# [ -f script ] echo 文件存在 || echo 文件不存在文件存在[[]]双中括号条件测试语法及示例[[]]条件测试的语法格式为[[ 判断表达式 ]]⚠️双中括号里的两端也要有空格。# 判断文件是否存在[rootlocalhost ~18:25:58]# [[ -f script ]] echo 文件存在 || echo 文件不存在文件存在[]、[[]]、(())的用法小结整数加双引号的比较是对的。[[]]中用类似-eq等的写法是对的[[]]中用类似、的写法也可能不对有可能会只比较第一位逻辑结果不对。[]中用类似、的写法在语法上虽然可能没错但逻辑结果不对可以使用、!正确比较。(())中不能使用类似-eq等的写法可以使用类似、的写法。文件判断表达式文件测试常用选项-d 文件d的全拼为directory文件存在且为目录则为真即判断表达式成立。-f 文件f的全拼为file文件存在且为普通文件则为真即判断表达式成立。-e 文件e的全拼为exist文件存在则为真即判断表达式成立。区别于-f-e不辨别是目录还是文件。-r 文件r的全拼为read文件存在且可读则为真即判断表达式成立。-s 文件s的全拼为size文件存在且文件size不为0则为真即判断表达式成立。-w 文件w的全拼为write文件存在且可写则为真即判断表达式成立。-x 文件x的全拼为executable文件存在且可执行则为真即判断表达式成立。-L 文件L的全拼为link文件存在且为链接文件则为真即判断表达式成立。f1 -nt f2nt的全拼为newer than文件fl比文件f2新则为真即判断表达式成立。根据文件的修改时间来计算。f1 -ot f2ot的全拼为older than文件fl比文件f2旧则为真即判断表达式成立。根据文件的修改时间来计算。字符串判断表达式字符串测试操作符的作用包括比较两个字符串是否相同、测试字符串的长度是否为零、字符串是否为NULL等。常用字符串测试操作符-n “字符串”若字符串的长度不为0则为真即判断表达式成立n可以理解为no zero。-z “字符串”若字符串的长度为0则为真即判断表达式成立z可以理解为zero的缩写。“串1” “串2”若字符串1等于字符串2则为真即判断表达式成立可使用“代替”。“串1” ! “串2”若字符串1不等于字符串2则为真即判断表达式成立但不能用!“代替”!。以下是针对字符串测试操作符的提示对于字符串的测试一定要将字符串加双引号之后再进行比较如[ -n $myvar ]特别是使用[]的场景。比较符号例如和!的两端一定要有空格。
Shell变量基础与进阶:从入门到精通
Shell 变量基础知识变量是暂时存储数据的地方及数据标记所存储的数据存在于内存空间中通过正确地调用内存空间中变量的名字就可以取出与变量对应的数据。变量的内容一般要加双引号以防止出错特别是当值里的内容之间有空格时。# 赋值变量变量名xxx[rootlocalhost ~18:56:59]# name123456# 加$[rootlocalhost ~18:58:49]# echo $name123456变量类型变量根据范围可分为两类全局变量在创建它们的 Shell及其派生出来的任意子进程 Shell 中使用。局部变量只能在创建它们的 Shell 函数或 Shell 脚本中使用。变量根据是否是用户自定义也可分为两类普通变量也称为常规变量由开发者在开发脚本程序时创建。环境变量定义shell 执行环境。环境变量又可分为自定义环境变量和bash内置的环境变量。环境变量环境变量一般是指用export内置命令导出的变量用于定义 Shell 的运行环境保证 Shell 命令的正确执行。Shell 通过环境变量来确定登录用户名、命令路径、终端类型、登录目录等所有的环境变量都是系统全局变量可用于所有子进程中这包括编辑器、 Shell 脚本和各类应用。环境变量可以在命令行中设置和创建但用户退出命令行时这些变量值就会丢失因此如果希望永久保存环境变量可在用户家目录下的.bash_profile或.bashrc(非用户登录模式特有例如远程SSH)文件中或者全局配置/etc/bashrc(非用户登录模式特有例如远程SSH)或/etc/profile文件中定义。在将环境变量放入上述的文件中后每次用户登录时这些变量都将被初始化。按照系统规范所有环境变量的名字均采用大写形式。在将环境变量应用于用户进程程序之前都应该用export命令导出定义。有一些环境变量比如HOME、PATH、USER等在用户登录之前就已经被/bin/login程序设置好了。通常环境变量被定义并保存在用户家目录下的.bash_profile文件或全局的配置文件/etc/profile中。部分bash环境变量展示EDITOR默认编辑器。HISTFILE历史文件位置。HISTSIZE历史命令个数。HISTTIMEFORMAThistory历史命令显示格式。PS1命令行提示符。LANGShell 环境语言。PATH命令搜素路径。HOME当前用户家目录。USER当前用户的用户名。UID当前用户的用户ID。PWD当前 Shell 路径。IFS字符串分隔符。在查看设置的变量时有3个命令可以显示变量的值set 命令输出所有的变量包括全局变量和局部变量。env 命令只显示全局变量包括 shell 的环境。declare 命令输出所有的变量、函数、整数和已经导出的变量。set -o命令显示bash Shell 的所有参数配置信息。设置环境变量1. 设置环境变量如果想要设置环境变量就要在给变量赋值( value )之后或在设置变量时使用export命令具体设置见下文的示例。其实除了export命令带-x选项的declare内置命令也可以完成同样的功能注意此处不要在变量名前面加$。export命令和declare命令的格式如下export 变量名value变量名value ; export 变量名declare -x 变量名value示例exportNAMEcsrdeclare-xNAMEcsrNAMEcsr;exportNAME下面来看看让环境变量永久生效的常用设置文件。用户的环境变量配置文件~/.bash_profile和~/.bashrc。推荐在~/.bashrc文件中设置。全局环境变量的配置文件/etc/profile、/etc/bashrc、/etc/profile.d/。**推荐在 /etc/bashrc 文件中设置。**若要在登录后初始化或显示加载内容则把脚本文件放在/etc/profile.d/下即可无须加执行权限)。2. 设置登录后提示信息第一种是在/etc/motd里增加提示的字符串如下[rootlocalhost ~20:53:49]# vim /etc/motdwelcome to csr linux Shell training.登录后第二种是在 /etc/profile.d/ 下面增加如下脚本。[rootlocalhost ~ 20:57:39]# vim /etc/profile.d/csr.sh echo welcome to csr linux Shell training.补充登录前提示符由文件 /etc/issue 提供。上一次登录记录由ssh服务提供在/etc/ssh/sshd_config文件中配置PrintLastLog yes默认启用。显示与取消环境变量用echo或printf命令打印环境变量。用env或set显示默认的环境变量。用unset消除本地变量和环境变量。环境变量小结变量名通常要大写。变量可以在自身的 Shell 及子 Shell 中使用。常用export来定义环境变量。执行env默认可以显示所有的环境变量名称及对应的值。输出时用$变量名取消时用unset变量名。书写crond定时任务时要注意脚本要用到的环境变量最好先在所执行的 Shell 脚本中重新定义。如果希望环境变量永久生效则可以将其放在用户环境变量文件或全局环境变量文件里。普通变量定义变量名一般是由字母、 数字 、下划线组成的不能以数字开头变量值可以用单引号或双引号引起来也可不加引号但是这三者的含义是不同的。把命令的结果作为变量的内容赋值**变量名(command)∗∗把命令用∗∗(command)** 把命令用**(command)∗∗把命令用∗∗()**括起来生产场景中把命令的结果作为变量的内容进行赋值的方法在脚本开发时很常见。Shell 变量进阶知识Shell 中特殊变量Shell 位置参数变量在 Shell 中存在一些特殊且重要的变量例如$0、$1我们称之为位置参数变量。要从命令行、函数或脚本执行等处传递参数时就需要在 Shell 脚本中使用位置参数变量。部分位置参数变量如下$0获取当前执行的Shell 脚本的文件名如果执行脚本包含了路径那么就包括脚本路径。**n∗∗获取当前执行的Shell脚本的∗∗第n个参数值∗∗。如果n大于9则用大括号括起来例如n**获取当前执行的 Shell 脚本的**第n个参数值**。如果n大于9则用大括号括起来例如n∗∗获取当前执行的Shell脚本的∗∗第n个参数值∗∗。如果n大于9则用大括号括起来例如{10}接的参数以空格隔开。$#获取当前执行的 Shell 脚本后面接的参数数量。**∗∗∗获取当前Shell脚本所有传参的参数不加引号和‘***获取当前 Shell 脚本所有传参的参数不加引号和∗∗∗获取当前Shell脚本所有传参的参数不加引号和‘相同如果给∗‘加上双引号例如‘*加上双引号例如∗‘加上双引号例如‘*则表示将所有的参数视为单个字符串相当于$1 $2 $3。**∗∗获取当前Shell脚本所有传参的参数不加引号和**获取当前 Shell 脚本所有传参的参数不加引号和∗∗获取当前Shell脚本所有传参的参数不加引号和*相同如果给加上双引号例如‘加上双引号例如加上双引号例如‘则表示将所有的参数视为不同的独立字符串相当于$1、“$2”、“$3”…这是将多参数传递给其他程序的最佳方式因为它会保留所有的内嵌在每个参数里的任何空白。[rootlocalhost ~10:49:43]# vim showargs.sh#!/bin/bashecho$0echo$1echo$2echo$10echo${10}echo$#echo$*echo$*echo$echo$[rootlocalhost ~10:59:18]# bash showargs.sh {a..z}showargs.sh a b a0 j26a b c d e f g h i j k l m n o p q r s t uvw x y z a b c d e f g h i j k l m n o p q r s t uvw x y z a b c d e f g h i j k l m n o p q r s t uvw x y z a b c d e f g h i j k l m n o p q r s t uvw x y zShell 进程中的特殊状态变量$?作用获取执行上一个指令的执行状态返回值0为成功非零为失败这个变量最常用。[rootlocalhost ~11:22:22]# ll[rootlocalhost ~11:23:04]# echo $?0Shell 内置变量命令bash Shell 包含一些内置命令。 这些内置命令在目录列表里是看不见的它们由 Shell 本身提供。常用的内部命令有echo、eval、exec、read、shift等。echoecho命令参数选项-n不换行输出内容。-e解析转义字符见下面的字符转义字符:\n换行。\t制表符tab)。\b退格。\r回到行首。[rootlocalhost ~14:36:18]# echo -n CSR;echo csrCSRcsr[rootlocalhost ~15:03:59]# echo -e CSR \n csrCSR csr[rootlocalhost ~15:08:09]# echo -e CSR \ncsrCSR csr[rootlocalhost ~15:16:30]# echo -e CSR\tcsrCSR csr[rootlocalhost ~15:27:50]# echo -ne 123\b;echo haha12haha[rootlocalhost ~15:32:09]# echo -e CSR\rhahahahaeval当 Shell 程序执行到 eval 语句时 Shell 读入参数args并将它们组合成一个新的命令然后执行。[CSRlocalhost ~11:00:14]$vimnoeval.sh[CSRlocalhost ~11:01:20]$bashnoeval.sh hello$1[CSRlocalhost ~11:02:03]$bashnoeval.sh hello world$2[CSRlocalhost ~11:02:09]$vimeval.shevalecho \$$#[CSRlocalhost ~11:10:02]$basheval.sh hello world world[CSRlocalhost ~11:12:10]$basheval.sh hello haha nihao it itread从标准输入读取字符串等信息 传给 Shell 程序内部定义的变量。[rootlocalhost ~15:40:37]# vim read.sh#!/bin/bashread-p输入你想要说的话strecho你想说的话是$str[rootlocalhost ~16:44:30]# bash read.sh输入你想要说的话hello 你想说的话是hello# 静默输入[rootlocalhost ~16:58:53]# read -s -p 请设置用户密码 password请设置用户密码[rootlocalhost ~17:09:39]# echo $password123开发脚本password实现类似passwd工具更改密码。[rootlocalhost ~17:57:03]# vim scr_password#!/bin/bashecho更改用户$1的密码read-sp新的密码password1echoread-sp重新输入新的密码password2echoecho$password1|passwd--stdin$1[rootlocalhost ~17:57:28]# bash ./scr_password CSR更改用户 CSR 的密码 新的密码 重新输入新的密码 Changing passwordforuser CSR. passwd: all authentication tokens updated successfully.execexec 命令能够在不创建新的子进程的前提下 转去执行指定的命令 当指定的命令执行完毕后 该进程 也就是最初的 Shell ) 就终止了。[CSRlocalhost ~10:24:51]$sudo-i[rootlocalhost ~10:25:31]# psPID TTY TIME CMD1609pts/0 00:00:00bash1690pts/0 00:00:00su1719pts/0 00:00:00su1720pts/0 00:00:00bash1733pts/0 00:00:00ps[rootlocalhost ~10:25:35]# exec sleep 10You have new mailin/var/spool/mail/root# sleep命令运行完成后自动返回到原先普通用户shell了。[CSRlocalhost ~10:26:38]$shift[CSRlocalhost ~11:33:21]$vimshift.sh#!/bin/bashecho$1shiftecho$1[CSRlocalhost ~11:44:04]$bashshift.sh1234512变量的数值计算实践算术运算符如果要执行算术运算就会离不开各种运算符号和其他编程语言类似Shell 也有很多算术运算符。下面就给大家介绍一下常见的 Shell 算术运算符、-一元正号和负号。、-加法和减法。*、/、乘法、除法、取余取模。**幂运算。、–增加及减少可前置也可放在变量结尾。!、、||逻辑非取反)、逻辑与and)、逻辑或or)。、、、比较符号小于、小于等于、大于、大于等于。、!、比较符号相等、不相等对于字符串也可以表示相当于。、向左移位、向右移位。~、|、、^按位取反、按位异或、按位与、按位。、、-、*、/、%赋值运算符例如a1相当于aa1a-1相当于aa-1。Shell 中常见的算术运算命令(())用于整数运算的常用运算符效率很高。let用于整数运算类似于(())。expr可用于整数运算但还有很多其他的额外功能。bcLinux下的一个计算器程序适合整数及小数运算。$[]用于整数运算。awkawk 既可以用于整数运算也可以用于小数运算。declare定义变量值和属性-i参数可以用于定义整形变量做运算。(()) 双小括号数值运算命令双小括号 (()) 的作用是进行数值运算与数值比较它的效率很高用法灵活是企业场景运维人员经常采用的运算操作符。5.2.1 (()) 双小括号数值运算的基础语法双小括号 (()) 的操作方法((ii1))此种书写方法为运算后赋值法即将i1的运算结果赋值给变量i。注意不能用echo ((iil))输出表达式的值可以用echo $((iil))输出其值。**i((i1))∗∗可以在‘(())‘前加‘((i1))**可以在 (()) 前加 ((i1))∗∗可以在‘(())‘前加‘ 符表示将表达式运算后赋值给i。(( 87 55))可以进行比较操作还可以加入逻辑与和逻辑或用于条件判断。**echo((21))∗∗需要直接输出运算表达式的运算结果时可以在‘(())‘前加‘((21))**需要直接输出运算表达式的运算结果时可以在 (()) 前加 ((21))∗∗需要直接输出运算表达式的运算结果时可以在‘(())‘前加‘ 符。(()) 双小括号数运算实践示例1[CSRlocalhost ~13:49:25]$echo$((6*3))18[CSRlocalhost ~13:59:25]$a3[CSRlocalhost ~13:59:32]$b8[CSRlocalhost ~13:59:36]$echo$((a*b))24示例2[CSRlocalhost ~14:09:14]$echo$((a23**2-4%3))10[CSRlocalhost ~14:11:46]$a$((100*(1001)/2))[CSRlocalhost ~14:27:44]$echo$a5050特殊运算符# 特殊运算符[CSRlocalhost ~14:35:27]$a11;echo$((a1))12# 比较和判断[CSRlocalhost ~14:35:50]$((15))[CSRlocalhost ~14:36:57]$echo$?1比较和判断# 执行 echo $((a)) 和 echo $((a--)) 命令输出整个表达式时输出的值即为 a 的值表达式执行完毕后会对a进行、--的运算[CSRlocalhost ~15:20:29]$a10[CSRlocalhost ~15:20:38]$echo$((a))10[CSRlocalhost ~15:21:23]$echo$((a))11[CSRlocalhost ~15:22:42]$echo$((a))12# 执行 echo $((a)) 和 echo $((--a)) 命令输出整个表达式时会先对a进行、--的运算然后再输出表达式的值即为a运算后的值。[CSRlocalhost ~15:22:45]$echo$((--a))12[CSRlocalhost ~15:23:23]$echo$((--a))11通过 (())运算后赋值给变量[CSRlocalhost ~15:30:07]$num99[CSRlocalhost ~15:31:00]$echonum$((num1))num100let 命令let运算命令的语法格式为let 表达式let表达式的功能等同于((表达式))[CSRlocalhost ~16:58:31]$i2[CSRlocalhost ~16:58:46]$echo$((i2))4[CSRlocalhost ~16:59:43]$leti8[CSRlocalhost ~17:03:35]$echo$i12expr 命令命令既可以用于整数运算也可以用于相关字符串长度、匹配等的运算处理。expr 命令的基本用法示例[CSRlocalhost ~17:17:06]$expr2222[CSRlocalhost ~17:17:14]$expr224[CSRlocalhost ~17:17:27]$expr2\*24[CSRlocalhost ~17:18:18]$expr2*22*2[CSRlocalhost ~17:19:00]$expr2*2expr: syntax error在使用expr时运算符及用于计算的数字左右都至少有一个空格否则会报错。使用乘号时必须用反斜线屏蔽其特定含义因为 Shell 可能会误解星号的含义。expr 的企业级实战案例详解例1# 计算字符串的长度[CSRlocalhost ~17:51:26]$strabc123[CSRlocalhost ~17:53:14]$exprlength$str6例2# 打印下面语句中字符数不大于6 的单词[CSRlocalhost ~17:54:02]$vimscr.sh#!/bin/bashstringsThis world is the scriptforwordin$stringsdoif[$(exprlength$word)-le6];thenecho$wordfidone[CSRlocalhost ~18:08:09]$bashscr.sh This world is the scriptbc 命令bc是UNIX/Linux下的计算器因此除了可以作为计算器来使用还可以作为命令行计算工具使用。[CSRlocalhost ~20:43:12]$bcbc1.06.95 Copyright1991-1994,1997,1998,2000,2004,2006Free Software Foundation, Inc. This isfreesoftware with ABSOLUTELY NO WARRANTY. For detailstypewarranty. 2^3 8 scale4 2/3 .6666 qui [CSRlocalhost ~ 20:47:04]$ echo scale4;2/3|bc.6666awk 命令实现计算适合小数和整数特别是命令行计算尤其是小数运算很精确好用。[CSRlocalhost ~21:22:02]$echo3.58.8|awk{ print $1-$2 }-5.3Shell 脚本的条件测试条件测试方法综述执行条件判断表达式后通常会返回真或假就像执行命令后的返回值为0表示真非0表示假。在 bash 编程里条件测试常用的语法如下语法1test 判断表达式test命令和判断表达式之间至少有一个空格。语法2[ 判断表达式 ]和test命令的用法相同这是推荐方法。[]的边界和内容之间至少有一个空格。语法3[[ 判断表达式 ]]是比test和[]更新的语法格式。[[]]的边界和内容之间至少有一个空格。语法4(( 判断表达式 ))一般用于 if 语句。(())(双小括号两端不需要有空格。语法5comand命令的返回值确定表达式的真值或假值。有几个注意事项需要说明一下:语法1中的test命令和语法2中的[]是等价的语法3中的[[]]为扩展的test命令语法4中的(())常用于计算。建议使用相对友好的语法2即中括号[]的语法格式。在[[ ]]双中括号中可以使用通配符等进行模式匹配这是其区别于其他几种语法格式的地方。、||、、等操作符可以应用于[[]]中但不能应用于[]中在[]中一般用-a、-o、-gt(用于整数)、-lt(用于整数代替上述操作符。对于整数的关系运算也可以使用 Shell 的算术运算符(())。test 条件测试的简单语法及示例test条件测试的语法格式为test 判断表达式# 判断文件是否存在[rootlocalhost ~17:30:37]# test -f script echo 文件存在 || echo 文件不存在文件存在该语句表示如果file文件存在则输出true否则输出false。这里的是逻辑与||是逻辑或。test的-f参数用于测试文件是否为普通文件test命令若执行成功为真)则执行后面的命令而||后面的命令是test命令执行失败之后为假所执行的命令。另外逻辑操作符和||的两端既可以有空格也可以无空格。带空格看起来会更美观一些建议使用带空格的格式。[]中括号条件测试语法及示例[]条件测试的语法格式为[ 判断表达式 ]⚠️ 中括号内部的两端要有空格[]和test等价即test的所有判断选项都可以直接在[]里使用。# 判断文件是否存在[rootlocalhost ~18:25:15]# [ -f script ] echo 文件存在 || echo 文件不存在文件存在[[]]双中括号条件测试语法及示例[[]]条件测试的语法格式为[[ 判断表达式 ]]⚠️双中括号里的两端也要有空格。# 判断文件是否存在[rootlocalhost ~18:25:58]# [[ -f script ]] echo 文件存在 || echo 文件不存在文件存在[]、[[]]、(())的用法小结整数加双引号的比较是对的。[[]]中用类似-eq等的写法是对的[[]]中用类似、的写法也可能不对有可能会只比较第一位逻辑结果不对。[]中用类似、的写法在语法上虽然可能没错但逻辑结果不对可以使用、!正确比较。(())中不能使用类似-eq等的写法可以使用类似、的写法。文件判断表达式文件测试常用选项-d 文件d的全拼为directory文件存在且为目录则为真即判断表达式成立。-f 文件f的全拼为file文件存在且为普通文件则为真即判断表达式成立。-e 文件e的全拼为exist文件存在则为真即判断表达式成立。区别于-f-e不辨别是目录还是文件。-r 文件r的全拼为read文件存在且可读则为真即判断表达式成立。-s 文件s的全拼为size文件存在且文件size不为0则为真即判断表达式成立。-w 文件w的全拼为write文件存在且可写则为真即判断表达式成立。-x 文件x的全拼为executable文件存在且可执行则为真即判断表达式成立。-L 文件L的全拼为link文件存在且为链接文件则为真即判断表达式成立。f1 -nt f2nt的全拼为newer than文件fl比文件f2新则为真即判断表达式成立。根据文件的修改时间来计算。f1 -ot f2ot的全拼为older than文件fl比文件f2旧则为真即判断表达式成立。根据文件的修改时间来计算。字符串判断表达式字符串测试操作符的作用包括比较两个字符串是否相同、测试字符串的长度是否为零、字符串是否为NULL等。常用字符串测试操作符-n “字符串”若字符串的长度不为0则为真即判断表达式成立n可以理解为no zero。-z “字符串”若字符串的长度为0则为真即判断表达式成立z可以理解为zero的缩写。“串1” “串2”若字符串1等于字符串2则为真即判断表达式成立可使用“代替”。“串1” ! “串2”若字符串1不等于字符串2则为真即判断表达式成立但不能用!“代替”!。以下是针对字符串测试操作符的提示对于字符串的测试一定要将字符串加双引号之后再进行比较如[ -n $myvar ]特别是使用[]的场景。比较符号例如和!的两端一定要有空格。