Shell ❀ 基础变量类别与引用

Posted 无糖可乐没有灵魂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shell ❀ 基础变量类别与引用相关的知识,希望对你有一定的参考价值。

文章目录

二、变量与引用

变量是程序设计语言中的一个可以变化的量,变化的是变量的值。变量几乎所有的程序设计语言都有定义,并且其涵义也基本一致。在程序执行的过程中,保存数据的内存空间的内容可能会不断地发生变化,但是代表内存地址的变量名却保持不变。

1、变量命名

在shell中对于变量名称的规范如下:

  • 变量名可以由字母、数字、下划线组成,只能以字母与下划线开头;
  • 变量名的长度没有直接的规定,尽可能使用较短的字符串作为变量名。

2、变量类型

shell是一种动态类型语言和弱类型语言,在shell中,变量的数据类型不需要声明,变量的数据类型会根据不同的操作有所变化,shell中的变量是不分数据类型的,统一按照字符串存储。

弱类型语言强类型语言phpCPython都是强类型语言)

  • 强类型和弱类型主要是站在变量类型处理的角度进行分类的;
  • 强类型是指不允许隐式变量类型转换,弱类型则允许隐式类型转换;

3、变量定义

在shell中,当用户第一次使用某个变量名时,就同时定义了该变量名称,在变量的作用域内都可以使用此变量。

  • =前后不能有空格
[root@localhost shell]# a= 3
bash: 3: command not found...
[root@localhost shell]# a =3
bash: a: command not found...

[root@localhost shell]# a=3
[root@localhost shell]# echo $?
0
[root@localhost shell]# echo $a
3
  • 字符串类型建议用引号,尤其是特殊字符或有空格
# #号为注释符号,若不带引号则后面内容被注释,代码无效
[root@localhost ~]# echo #aaa

[root@localhost ~]# echo "#aaa"
#aaa

4、常用变量

主要有:通配符、内置变量、自定义变量、环境变量、全局变量、局部变量、位置变量、预定义变量。

4.1 内置通配符

在Linux系统中,通配符是一种特殊语句,主要有星号*和问号?,用来模糊搜索文件。当查找文件夹时,可以使用它来代替一个或多个真正字符;当不知道真正字符或者懒得输入完整名字时,常常使用通配符代替一个或多个真正的字符。

  • ?代表单个任意字符;
  • *代表多个任意字符。
  • []匹配括号内任意一个字符;
  • [-]代表某个范围内的单个字符;
  • [*]匹配不是中括号的字符;

案例演示:

# 准备环境
[root@localhost shell]# touch a,b,c,tt.cc
[root@localhost shell]# ls
a  b  c  tt.cc

# 匹配单个或多个字符
[root@localhost shell]# ls *.cc
tt.cc
[root@localhost shell]# ls ??.cc
tt.cc
# 匹配a或b单个字符
[root@localhost shell]# ls [ab]
a  b
# 匹配范围a-b的单个字符
[root@localhost shell]# ls [a-b]*
a  b
# 匹配非范围a-b的所有字符
[root@localhost shell]# ls [!a-b]*
c  tt.cc

4.2 内置变量

内置变量:系统本来就存在的变量,可直接使用的。在执行脚本的时候,可通过带参数传入脚本内部。

常见内置变量有:

  • USER当前系统登录用户

  • UID: 当前用户的UID;

  • HOME: 当前用户的家目录

  • SHELL: 当前使用的shell类型 /bin/bash;

  • BASHPID: 当前bash的进程编号;

  • HISTSIZE: 缓冲区记录命令历史的数量;

  • MAIL: 当前用户的邮件信息储存目录 /var/spool/mail/root

  • PATH: 当前系统环境变量

  • LANG: 系统使用的语言和编码字符集 en_US.UTF-8

  • RANDOM: 生成随机数,生成范围0~32767

  • PS1: 命令提示符;

  • OSTYPE: 操作系统类型 linux-gun;

  • HOSTTYPE: 主机类型 x86_64;

  • MACHTYPE: 机器类型 x86_64-redhat-linux-gnu;

[root@localhost ~]# echo $USER
root
[root@localhost shell]# echo $UID
0
[root@localhost shell]# echo $HOME
/root
[root@localhost shell]# echo $SHELL
/bin/bash
[root@localhost shell]# echo $BASHPID
2821
[root@localhost shell]# echo $HISTSIZE
1000
[root@localhost shell]# echo $MAIL
/var/spool/mail/root
[root@localhost shell]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost shell]# echo $RANDOM
3412
[root@localhost shell]# echo $PS1
[\\u@\\h \\W]\\$
[root@localhost shell]# echo $OSTYPE
linux-gnu
[root@localhost shell]# echo $HOSTTYPE
x86_64
[root@localhost shell]# echo $MACHTYPE
x86_64-redhat-linux-gnu

4.3 自定义变量

根据自己喜好所定义的变量。

  • 定义变量:变量名=变量值

  • 引用变量:$变量名$变量名

  • 查看变量:echo $变量名set(所有变量,包括自定义变量与环境变量)

  • 取消变量:unset 变量名(注:取消变量时不需要带$引用变量名称)

  • 作用范围:仅在当前脚本文件中有效

4.4 环境变量

环境变量是程序(操作系统命令和应用程序)的执行都需要运行环境,分为临时变量和永久变量。

# 使用命令export直接加入临时变量(系统重启后失效)
[root@localhost shell]# export back_dir2=/home/backup

# 修改系统加载文件加入永久变量
[root@localhost shell]# vim /etc/profile
export TEST_PATH=/etc
export PATH=$PATH:$TEST_PATH
[root@localhost ~]# source /etc/profile

# 查看所有环境变量
[root@localhost shell]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

# 查看单个环境变量
[root@localhost shell]# back_dir1=/home/backup
[root@localhost shell]# echo $back_dir1
/home/backup

4.5 变量的作用域

4.5.1 全局变量

全局变量可以在脚本中定义,也可以在函数中定义,脚本中定义的变量都是全局变量,其作用域从被定义开始一直到shell脚本结束或者被显示删除。

4.5.2 局部变量

与全局变量相比,局部变量的使用范围较小,通常仅限于某个程序段访问,在shell语言中,可以在函数内部通过local关键字定义局部变量,函数参数也是局部变量。

[root@localhost ~]# vim shell.sh 
#!/bin/bash

function test()
        local aaa=123
        echo "本地变量:$aaa"


test
echo "---------------"
echo "全局变量:$aaa"
[root@localhost ~]# sh shell.sh 
本地变量:123
---------------
全局变量:

4.6 位置变量

位置变量顾名思义就是脚本后面所附加的具体位置参数,如sh test.sh 1 2 3 ...,其中1、2、3分别对应的就是位置1的变量,位置2的变量,位置3的变量,以此类推。

$1$2$3$4$5$6$7$8$9

4.5.1 位置变量的左移操作

在某些脚本文件中,若定义了某个位置参数后,则该参数后续不会被使用,因此可以使用shift 命令左移位置变量,默认移动距离为1,使得变量的数字不用人为记忆就可以常用,写代码较为方便。

[root@localhost ~]# vim shell.sh
#!/bin/bash

echo "位置1的变量是:$1"
echo "位置2的变量是:$2"
shift 1
echo "位置3的变量是:$3"
shift 3
echo "位置7的变量是:$7"

[root@localhost ~]# sh  shell.sh a b c d e f g h i j k
位置1的变量是:a
位置2的变量是:b
位置3的变量是:d				# 实际是位置4的变量d,并不是c
位置7的变量是:k				# 实际是位置11的变量k,并不是g

4.5.2 执行脚本父目录绝对路径的获取方式

使用dirname可以直接获取脚本所处父目录的绝对路径

[root@localhost ~]# dirname test.sh 
.							# 表示当前目录
[root@localhost ~]# dirname /usr/local/lib/
/usr/local					# 父目录绝对路径

dirnamepwd的区别说明:

[root@localhost ~]# cd /usr/local/lib
[root@localhost lib]# cat /root/test.sh 
#!/bin/bash
echo "dirname $0"
path=$(dirname $0)
echo "$path"
pwd

[root@localhost lib]# sh /root/test.sh 
dirname /root/test.sh
/root					# dirname返回运行脚本的父目录绝对路径
/usr/local/lib			# pwd返回执行脚本的当前绝对路径

4.7 预定义变量

Linux系统默认预先定义的位置变量

$0		# 0位置参数,返回所执行脚本的名称
$*		# 所有参数,返回值为一个整体值,以空格连接所有参数
$@		# 所有参数,返回值会将所有位置的参数当做一个单独的字段,以回车连接所有参数
$#		# 参数个数
$$		# 当前进程PID
$!		# 上一个后台进程的PID
$?		# 上一个命令的返回值,0代表成功,非0代表失败

4.8 脚本变量案例

位置变量

[root@localhost ~]# vim test.sh 
#!/bin/bash
echo "脚本名称是:$0"
echo "第2个参数是:$2"
echo "所有参数是:$*"
echo "所有参数是:$@"
echo "参数个数是:$#"
echo "当前进程PID是:$$"

[root@localhost ~]# sh test.sh a b c d e f g
脚本名称是:test.sh
第2个参数是:b
所有参数是:a b c d e f g
所有参数是:a b c d e f g
参数个数是:7
当前进程PID是:4607

[root@localhost ~]# echo $?
0

预定义变量

[root@localhost shell]# cat a4.sh
#!/bin/bash

ping -c2 $1 &> /dev/null
if [ $? = 0 ];then
        echo "host $1 is ok!"
else
        echo "host $1 is down!"
fi
[root@localhost shell]# sh a4.sh 10.81.10.55
host 10.81.10.55 is ok!
[root@localhost shell]# echo $?
0

4.9 $*与$@的区别

[root@localhost shell]# set -- "I am" test command

# 返回值为一个整体值,以空格连接所有参数
[root@localhost shell]# for i in "$*";do echo $i;done
I am test command
# 返回值会将所有位置的参数当做一个单独的字段,以回车符连接所有参数
[root@localhost shell]# for i in "$@";do echo $i;done
I am
test
command

5、变量赋值与替换

5.1 变量和引号

shell语言中一共有三种引号,分别是单引号、双引号、反引号。

  • 单引号:字符作为普通字符出现,强转义;
  • 双引号:除了$\\'" 四个符号外,其余字符作为普通字符对待;
  • 反引号:引号内的内容被解释的shell命令;
[root@localhost shell]# echo "user is $USER"
user is root
[root@localhost shell]# echo 'user is $USER'
user is $USER
[root@localhost shell]# echo "user is `whoami`"
user is root
[root@localhost shell]# echo 'user is `whoami`'
user is `whoami`
# 正确使用转义符
[root@localhost ~]# echo "aaa\\"bbb"
aaa"bbb

5.2 只读变量

将变量配置成为readonly类型,该变量不可被更改内容,也不能unset(不建议使用此操作);

readonly [-fap] [变量定义]
# -f 定义只读函数
# -a 定义只读数组变量
# -p 显示系统中全部的变量列表

演示案例:

[root@localhost ~]# readonly aaa=123
[root@localhost ~]# readonly -p |grep aaa
declare -r aaa="123"

# 只读变量无法通过unset取消
[root@localhost ~]# unset aaa
-bash: unset: aaa: cannot unset: readonly variable

只读变量删除方法参考链接

5.3 变量运算

5.3.1 常见运算符

  • + - :加 减
  • * / % :乘 除 取余
  • ** :幂次方
  • ++ -- :增加 减少
  • ! && || :非 与 或
  • < <= > >= :小于 小于等于 大于 大于等于
  • == != = :相等 不等 相当于
  • << >> :左移 右移
  • ~ | & ^ :取反 按位异或 按位与 按位或
  • = += -+ *= /+ %= :赋值运算符,a+=1相当于a=a+1
[root@localhost ~]# echo $((1+1))
2
[root@localhost ~]# echo $((8**2))
64
[root@localhost ~]# echo $((1++2))
3
[root@localhost ~]# echo $((1==2))		# 不等为0
0
[root@localhost ~]# echo $((1==1))		# 相等为1
1

5.3.2 常见运算命令

  • (()) :用于整数运算的常用运算符;
  • let :用于整数运算,类似于(())
  • expr :可用于整数运算;
  • bc :Linux下的一个计算器程序,适用于整数与小数运算;
  • $[] :用于整数运算;
  • awk :用于整数与小数运算;
  • declare :定义变量值和属性,-i 参数定义整形变量,做运算;
[root@localhost ~]# echo $((1+1))
2

[root@localhost ~]# echo $[ 1+2 ]
3

# 使用计算机小程序
[root@localhost shell]# bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 

2+2
4
1+1
2
^C
(interrupt) Exiting bc.

# let运算符
[root@localhost shell]# vim 1.sh 
#!/bin/bash

i=1
while [ $i -le 3 ]
do
	echo "$i"
	let i++				# 变量i叠加1
done
[root@localhost shell]# sh 1.sh 
1
2
3

5.3.3 变量子串说明

  • $parameter :返回变量$parameter的内容;
  • $#parameter :返回变量$parameter内容的长度(按字符计算,索引从1开始),适用特殊变量;
  • $parameter:offset :在变量$parameter中,从位置offset之后开始提取子串到结尾;
  • $parameter:offset:length :在变量$parameter中,从位置offset之后开始提取长度为length的子串;
  • $parameter#word :从变量$parameter开头开始删除最短匹配的word子串;
  • $parameter##word :从变量$parameter开头开始删除最长匹配的word子串;
  • $parameter%word :从变量$parameter结尾开始删除最短匹配的word子串;
  • $parameter%%word :从变量$parameter结尾开始删除最长匹配的word子串;
  • $parameter/pattern/string :使用string代替第一个匹配的pattern;
  • $parameter//pattern/string :使用string代替所有匹配的pattern
# 配置环境
[root@localhost shell]# filename=testfile.tar.gz

# 返回变量内容
[root@localhost shell]# echo $filename
testfile.tar.gz
# 返回变量长度
[root@localhost shell]# echo $#filename
15
# 从第7字节开始提取子串到结尾
[root@localhost shell]# echo $filename:6
le.tar.gz
# 从开头匹配删除最短的.子串,即从开头匹配到第一个.的字符串删除,注意通配符*的位置
[root@localhost shell]# echo $filename#*.
tar.gz
# 从开头匹配删除最长的.子串,即从开头匹配到最后一个.的字符串删除
[root@localhost shell]# echo $filename##*.
gz
# 从结尾匹配删除最短的.子串,即从结尾匹配到第一个.的字符串删除
[root@localhost shell]# echo $filename%.*
testfile.tar
# 从结尾匹配删除最短的.子串,即从结尾匹配到最后一个.的字符串删除
[root@localhost shell]# echo $filename%%.*
testfile
# 使用zip替换tar,只替换匹配的第一个tar字符串
[root@localhost shell]# echo $filename/tar/zip
testfile.zip.gz
  • $parameter:-word: 如果parameter的变量值为空或未赋值,则会返回word字符串并替代变量的值用途:如果变量未定义,则返回备用的值,防止变量为空值或因未定义而导致异常。
[root@localhost ~]# echo $var1

[root@localhost ~]# var2=$var1:-hello			# 变量1为空,返回hello
[root@localhost ~]# echo $var2
hello
[root@localhost ~]# echo $var1

[root@localhost ~]# var1="hello"
[root@localhost ~]# echo $var1
hello
[root@localhost ~]# var2=$var1:-world			# 变量1不为空,返回变量原内容
[root@localhost ~]# echo $var2
hello
[root@localhost ~]# unset var1 var2				# 清理变量(选择性操作)
  • $parameter:=word :如果parameter的变量值为空或未赋值,则设置这个变量值为word,并返回其值。位置变量和特殊变量不适用。
[root@localhost ~]# var2=$var1:=world			# 变量1为空,将world赋值给变量1和变量2
[root@localhost ~]# echo $var2
world
[root@localhost ~]# echo $var1
world
[root@localhost ~]# unset var1 var2
[root@localhost ~]# var1="hello"
[root@localhost ~]# var2=$var1:=world			# 变量1不为空,将变量1的值hello赋值给变量2
[root@localhost ~]# echo $var2
hello
[root@localhost ~]# echo $var1
hello
  • $parameter:?word :如果parameter变量值为空或未赋值,那么word字符串将被作为标准错误输出,否则输出变量的值。
[root@localhost ~]# var2=$var1:?world			# 变量1为空,将world作为错误输出
-bash: var1: world
[root@localhost ~]# unset var1 var2
[root@localhost ~]# var1="hello"
[root@localhost ~]# var2=$var1:?world			# 变量1不为空,将变量1的值hello赋值给变量2
[root@localhost ~]# echo $var2
hello
[root@localhost ~]# echo $var1
hello
  • $parameter:+word :如果parameter变量值为空或未赋值,则什么都不做,否则word字符串将替代变量的值。
[root@localhost ~]# var2=$var1:+world			# 变量1为空,无返回
[root@localhost ~]# echo $var2

[root@localhost ~]# unset var1 var2
[root@localhost ~]# var1="hello"
[root@localhost ~]# var2=$var1:+world			# 变量1不为空,将world赋值给变量2
[root@localhost ~]# echo $var2
world
[root@localhost ~]# echo $var1
hello

5.3.4 操作案例

基本要求:删除7天前的过期数据备份,规定path则删除path路径下的过期文件,若不规定path,则删除/tmp目录下过期文件

[root@localhost shell]# cat a1.sh
#!/bin/bash
find $path:-/tmp -name "*.tar.gz" -type f -mtime +7 | xargs rm -f
#指定path或tmp路径下,后缀为.tar.gz的任意文件,创建时间为7天之后
#xargs 参数传输命令
#将寻找到的文件,以参数传递给rm命令进行删除

[root@localhost shell]# sh a1.sh /

6、输入与输出

在Linux中输入与输出的方式种类较多,此处介绍两种最常用的输入与输出方法,read输入与echo输出;

6.1 read输入

在Linux系统中,read命令用于从标准输入读取数值,这个命令可以用来读取键盘的输入值,因此常用于shell编程中的输入语法;

6.1.1 命令格式

read [-ers] [-a aname] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
  • -a:后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符;
  • -d:后面跟一个标志符,其实只有其后的第一个字符有用,作为结束的标志;
  • -p:后面跟提示信息,即在输入前打印提示信息;
  • -e:在输入的时候可以使用命令补全功能;
  • -n:后跟一个数字,定义输入文本的长度,如-n2意味限制输入字符为2个字符;
  • -r:屏蔽 \\,若没有该选项,\\ 作为一个转义字符,否则 \\ 就是个正常的字符无需进行转义(\\);
  • -s:安静模式,在输入字符时不再屏幕上显示,例如login时输入密码无回显,等同于使用stty ‐echo关闭回显功能,使用stty echo打开回显功能;
  • -t:后面跟秒数,定义输入字符的等待时间,如-t 3意味3秒内输入,常用于条件判断语句中的定时输入;
  • -u:后面跟fd,从文件描述符中读入,该文件描述符可以是exec新开启的;

6.1.2 操作案例

  1. 使用read命令输入一个信息;
#!/bin/bash
 
echo "输入一个信息:"  
# 默认有一个换行符
read aaa 
echo "你输入的信息是:$aaa"  

输出结果:

[root@localhost ~]# sh 1.sh 
输入一个信息:
aaa
你输入的信息是:aaa
  1. 使用-p参数提供一个提示信息;
#!/bin/bash

read -p "输入一个信息:" aaa 
echo "你输入的信息是:$aaa"  

输出结果:

[root@localhost ~]# sh 1.sh 
输入一个信息:aaa
你输入的信息是:aaa
  1. 使用-t参数指定输入时间限制;
#!/bin/bash

if read -t 5 -p "输入一个信息:" aaa;then
    echo "你输入的信息是 $aaa"
else
    echo "输入超时!"
fi

输出结果:

[root@localhost ~]# sh 1.sh #不输入任何信息,等待5s
输入一个信息:输入超时!
  1. 使用-n参数指定输入字符长度;
#!/bin/bash

read -n1 -p "Do you want to continue [Y/N]?" answer
case $answer in
Y | y)
    echo "fine ,continue";;
    # 若是需要换行,则需要给echo添加参数-e,支持正则表达式
    # echo -e "\\nfine ,continue";;
N | n)
    echo "ok,good bye";;
*)
    echo "error choice";;
esac

输出结果:

[root@localhost ~]# sh 1.sh 
Do you want to continue [Y/N]?yfine ,continue
  1. 使用-s参数指定输入信息不得回显在终端上(数据是显示的,read命令将文本颜色设置为背景颜色从而导致无法查看),常用于密码输入等位置;
#!/bin/bash

read  -s  -p "请输入密码:" pass
echo -e "\\n密码是 $pass"

输出结果:

[root@localhost ~]# sh 4.sh 
请输入密码:
密码是 aaa
  1. 使用read命令读取文件中的每一行内容;
#!/bin/bash

# 从第一行开始
count=1
# 读取内容赋值给line变量
cat test.txt | while read line    
do
   # 显示行号:内容
   echo "Line $count:$line"
   # 行号自增加
   count=$[ $count + 1 ]
done
echo "finish"

输出结果:

[root@localhost ~]# sh 1.sh 
Line 1:this is test
Line 2:this is test
finish
  1. 使用-e参数,输入时可以使用tab键补全内容;
[root@localhost ~]# read -e -p "输入文件名:"
输入文件名:1.
1.py  1.sh  
输入文件名:1.py

6.2 echo输出

Linux的echo命令在shell编程中十分常见,echo命令的功能是在终端上打印出一段文字;

6.2.1 命令格式

echo [--help][--version]echo [Options][字符串]
  • -n:不要输出衍生的新行, 不加此参数时默认输出时换行;

  • -e:启用反斜线转义解释;

  • -E:禁用反斜线转义解释(默认参数);

使用-e参数后,echo可以支持如下转义序列:

  • \\a:发出警告声;
  • \\b:删除前一个字符;
  • \\c:不产生进一步输出,只输出 \\c 之前的内容;
  • \\f:换行,但下一行内容起始位置和上一行从 \\f 处换行的位置对齐,效果等同于 \\v
  • \\n:换行,下一行内容和上一行内容对齐;
  • \\r:换行,光标移至行首,输出 \\r 后面的内容;
  • \\v:换行,但下一行内容起始位置和上一行从 \\v 处换行的位置对齐,效果等同于 \\f
  • \\t:插入tab水平制表符;
  • \\:反斜线,插入 \\ 反斜线字符,若转义的内容如 \\t ,系统会将转义后的反斜杠与 t 进行结合,生成为 \\t(制表符),从而实现tab水平制表功能,因此就需要将 \\t 分别转义,即 \\\\ + \\t(第一个\\均为转义符号);
  • \\nnn:插入nnn(八进制)所代表的ASCII字符;
  • \\0NNN:八进制值表示的字节NNN(1到3个数字);
  • \\xHH:十六进制值表示的字节NNN(1到2个数字);

6.2.2 操作案例

  1. 使用-n参数
[root@localhost ~]# echo -n aaa ; echo bbb ; echo ccc
aaabbb
ccc
  1. 使用-e参数
# \\b删除前一个字符a
[root@localhost ~]# echo -e "this is a\\b test"
this is  test

# \\c只输出前面内容(回车字符也被删除)
[root@localhost ~]# echo -e "aaa\\c bbb ccc"
aaa[root@localhost ~]# 

# \\f换行输出,下一行起始位置等于换行位置(等同于\\v)
[root@localhost ~]# echo -e "this is \\f test"
this is 
         test

# \\n换行符
[root@localhost ~]# echo -e "this is \\n test"
this is 
 test

# \\r切换到行首换行,使用\\r后面的est替换开始的thi
[root@localhost ~]# echo -e "this is t\\rest"
ests is t

以上是关于Shell ❀ 基础变量类别与引用的主要内容,如果未能解决你的问题,请参考以下文章

Shell ❀ 基础变量类别与引用

Shell ❀ 学习笔记与知识点梳理

Shell ❀ 学习笔记与知识点梳理

Shell ❀ 学习笔记与知识点梳理

bash脚本变量变量类型

linux——Shell 脚本基础篇(变量类型,变量操作,定义,运算与逻辑关系)