Shell ❀ 基础变量类别与引用

2023-05-16

文章目录

  • 二、变量与引用
    • 1、变量命名
    • 2、变量类型
    • 3、变量定义
    • 4、常用变量
      • 4.1 内置通配符
      • 4.2 内置变量
      • 4.3 自定义变量
      • 4.4 环境变量
      • 4.5 变量的作用域
        • 4.5.1 全局变量
        • 4.5.2 局部变量
      • 4.6 位置变量
        • 4.5.1 位置变量的左移操作
        • 4.5.2 执行脚本父目录绝对路径的获取方式
      • 4.7 预定义变量
      • 4.8 脚本变量案例
      • 4.9 \$*与\$@的区别
    • 5、变量赋值与替换
      • 5.1 变量和引号
      • 5.2 只读变量
      • 5.3 变量运算
        • 5.3.1 常见运算符
        • 5.3.2 常见运算命令
        • 5.3.3 变量子串说明
        • 5.3.4 操作案例
    • 6、输入与输出
      • 6.1 read输入
        • 6.1.1 命令格式
        • 6.1.2 操作案例
      • 6.2 echo输出
        • 6.2.1 命令格式
        • 6.2.2 操作案例
        • 6.2.3 结果输出到指定文件
        • 6.2.4 引号的输出
        • 6.2.7 彩色输出
        • 6.2.8 在脚本中使用颜色输出
          • 6.2.8.1 定义颜色变量
          • 6.2.8.2 定义颜色动作
        • 6.2.9 使用tput修改颜色
    • 7、$( ) $(( )) $[ ] $[[ ]] ${ }的区别
      • 7.1 $( ) 与\` \`命令的替换
      • 7.2 ${ }变量替换
        • 7.2.1 变量替换
        • 7.2.2 变量截取
        • 7.2.3 匹配删除
      • 7.3 $ [ ] 与$(( )) 整数运算

二、变量与引用

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

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

# \t制表符
[root@localhost ~]# echo -e "this is t\test"
this is t	est

# \\反斜杠,需要注意的是反斜杠的转义若是转义后的结果是转义序列内容,需要进行两次转义
[root@localhost ~]# echo -e "this \\is test"
this \is test
[root@localhost ~]# echo -e "this is \\\test"		# \t为制表符,因此需要做两次转义
this is \test

6.2.3 结果输出到指定文件

使用重定向>与追加重定向>>指定到对应文件的路径(绝对路径或相对路径);

echo "this is test" > /tmp/test.txt

6.2.4 引号的输出

引号的输出:若是需要输出双引号,需要将双引号包含在单引号内,或使用转义符号\进行转义;

不加引号:字符串原样输出,变量会被替换,除了 \ 和 空格会产生区别。

# 双引号
[root@localhost ~]# echo 'Hello "World"'
Hello "World"
[root@localhost ~]# echo Hello \"World\"
Hello "World"

# 单引号
[root@localhost ~]# echo "Hello 'World'"
Hello 'World'
[root@localhost ~]# echo Hello \'World\'
Hello 'World'

# 不加引号
[root@localhost shell]# echo \a    \b
a b
[root@localhost shell]# echo "\a     \b"
\a     \b

6.2.7 彩色输出

echo命令支持修改字体类型,字体背景颜色与字体颜色,转义序列\033可以用来改变字体属性,若要转义序列生效,必须使用echo -e选项;

echo -e " \033[颜色1;颜色2m 要展示的文字  \033[0m "
# -e:echo选项,支持转义序列,必须存在
# \033[颜色1;颜色2m:转义序列,本身为一个整体,中间没有空格
# \033[:转义序列的开始,\033代表ESC符号,也可以使用\E或\e代替
# 颜色1和颜色2:根据数值决定前景色与背景色;
# m:转义序列的终止符号
# \033[0m:表示将颜色恢复成原来的配色

颜色的转义代码:

[0m: 正常
[1m: 粗体
[4m: 字体加上下划线
[7m: 逆转前景和背景色
[8m: 不可见字符
[9m: 跨行字体
[30m: 灰色字体
[31m: 红色字体
[32m: 绿色字体
[33m: 棕色字体
[34m: 蓝色字体
[35m: 紫色字体
[36m: 浅蓝色字体
[37m: 浅灰字体
[38m: 黑色字体
[40m: 黑色背景
[41m: 红色背景
[42m: 绿色背景
[43m: 棕色背景
[44m: 蓝色背景
[45m: 紫色背景
[46m: 浅蓝色背景
[47m: 浅灰色背景

# 案例演示
[root@localhost ~]# echo -e " \033[31;42mtest\033[0m "
[root@localhost ~]# echo -e " \033[31mtest\033[0m "
# m为颜色的结束标记,注意空格的位置
[root@localhost ~]# echo -e " \033[31m test \033[0m "

6.2.8 在脚本中使用颜色输出

脚本中使用颜色的方式有两种:定义颜色变量、定义颜色动作

6.2.8.1 定义颜色变量

使用echo -e调用,此方式是将颜色定义为变量,使用命令调用对应变量即可完成颜色设置;

#!/bin/bash

# 定义颜色变量
RED='\E[1;31m'       # 红
GREEN='\E[1;32m'     # 绿
YELOW='\E[1;33m'     # 黄
BLUE='\E[1;34m'      # 蓝
PINK='\E[1;35m'      # 粉红
RES='\E[0m'          # 清除颜色

# 通过echo -e调用
echo -e  "${RED}Red color${RES}"
echo -e  "${YELOW}Yelow color${RES}"
echo -e  "${BLUE}Blue color${RES}"
echo -e  "${GREEN}Green color${RES}"
echo -e  "${PINK}Pink color${RES}"
6.2.8.2 定义颜色动作

直接调用使用,将echo也定义在变量内,此方式不需要过多的输入echo

#!/bin/bash

# 定义颜色动作, 把echo -e也定义到变量中
SETCOLOR_SUCCESS="echo -en \\E[1;32m"
SETCOLOR_FAILURE="echo -en \\E[1;31m"
SETCOLOR_WARNING="echo -en \\E[1;33m"
SETCOLOR_NORMAL="echo -en  \\E[0;39m"
 
# 使用时直接调用颜色动作即可
$SETCOLOR_SUCCESS && echo SUCCESS   
$SETCOLOR_FAILURE && echo FAILURE   
$SETCOLOR_WARNING && echo WARNING   
$SETCOLOR_NORMAL  && echo NORMAL

6.2.9 使用tput修改颜色

前面所学习的颜色修改方法都需要转义序列来实现,转义序列比较难以记忆,因此就需要一个更简单的方法来完成颜色的修改;tput命令会利用terminfo数据库中的信息,来控制终端,如光标控制、更改文本属性、文本涂色、控制屏幕等操作;

  • tput setab:用于设置背景色;
  • tput setaf:用于设置前景色;

数值与颜色的匹配方法:0 - 黑色、1 - 红色、2 - 绿色、 3 - 黄色、4 - 蓝色、5 - 洋红色、6 - 青色、7 - 白色

aaa=$(tput setaf 1)
bbb=$(tput setaf 2
ccc=$(tput setaf 3)
ddd=$(tput setaf 4)
eee=$(tput setaf 5)
fff=$(tput setaf 6)
ggg=$(tput setaf 7)
hhh=$(tput sgr 0)           #恢复默认终端
echo -e "${aaa}test \n${bbb}test \n${ccc}test \n${ddd}test \n${eee}test \n${fff}test \n${ggg}test${hhh}"

7、$( ) $(( )) $[ ] $[[ ]] ${ }的区别

7.1 $( ) 与` `命令的替换

在shell编程中,$( )与` `均可以表示命令的替换操作;将反引号或者括号内的命令进行执行,并将执行的结果返回到当前的命令中;

  • ` `反引号容易与单引号 ’ ’ 混淆,因此推荐使用$( )进行命令替换操作;在多层次的复合替换命令中,反引号需要进行转义操作,而$( )不需要转义操作;
  • $( )并不支持所有的类Unix系统,但是反引号支持全部的类Unix系统;

操作案例

# 直接使用命令以字符串输出
[root@localhost ~]# echo date
date
#  使用替换命令方式输出执行结果
[root@localhost ~]# echo `date`
Fri Apr 29 15:56:10 CST 2022
[root@localhost ~]# echo $(date)
Fri Apr 29 15:56:15 CST 2022

# $( )支持复合替换命令
[root@localhost ~]# echo $(echo $(date))
Fri Apr 29 15:57:10 CST 2022

# ` `需要转义方可支持复合替换命令
[root@localhost ~]# echo `echo `date``
date
[root@localhost ~]# echo `echo \`date\``
Fri Apr 29 15:57:32 CST 2022

7.2 ${ }变量替换

默认情况下, v a r 与 var与 var{var}是没有区别的,但是${ }的使用可以使得变量名称的范围更加精确;

# 输出变量A后面连接字符串B
[root@localhost shell]# A=linux
[root@localhost shell]# echo $A
linux
[root@localhost shell]# echo $AB		# 此时输出为变量AB,因此无返回

[root@localhost ~]# echo ${A}B
linuxB

7.2.1 变量替换

  • ${var}:变量原值。
[root@localhost ~]# var=test ; echo $var
test
[root@localhost ~]# echo ${var}
test
  • ${var:-word}:如果变量var为空或已经被删除(unset),则返回word,不改变变量var的值;若变量var的值不为空,则不返回word也不改变原值;
[root@localhost ~]# var= ; echo ${var:-word}
word
[root@localhost ~]# echo $var

  • ${var:=word}:如果变量var为空或已经被删除(unset),则返回word,并将变量var的值设置为word;若变量var的值不为空,则不返回word也不改变原值(该操作是一种提供默认值的常见方式);
[root@localhost ~]# var= ; echo ${var:=word}
word
[root@localhost ~]# echo $var
word
  • ${var:?word}:如果变量var为空或已经被删除(unset)那么将word送到标准错误输出,可以利用此特性来检测是否设置了变量的值;
  • ${var:+word}:如果变量var被定义,则返回word,不改变变量var的值;若变量var为空,不返回word也不改变原值;
[root@localhost ~]# var=test ; echo ${var:+word}
word
[root@localhost ~]# echo $var
test

7.2.2 变量截取

语法格式:

${变量名:起始位置:长度}
# 长度默认为1,可忽略或自设定长度

案例演示:

[root@localhost ~]# a=123456789
# 从左向右第5位开始截取到末尾
[root@localhost ~]# echo ${a:5}
6789
# 从左向右第3位开始截取,留4位
[root@localhost ~]# echo ${a:3:3}
456
# 先从左向右第2位开始截取,后从右向左截取第1位
[root@localhost ~]# echo ${a:2:-1}
345678
# 先从左向右第2位开始截取,后从右向左截取第2位
[root@localhost ~]# echo ${a:2:-2}
34567

7.2.3 匹配删除

语法格式:

  • #*chr:表示删除从左向右第一个遇到的字符chr及其左侧的字符;
  • ##*chr:表示删除从左向右最后一个遇到的字符chr及其左侧的字符;(贪婪模式)
  • %chr*:表示删除从右向左第一个遇到的字符chr及其左侧的字符;
  • %%chr*:表示删除从右向左最后一个遇到的字符chr及其左侧的字符;(贪婪模式)

参数说明:

  • *:匹配所有字符;
  • %:最短尾匹配;
  • %%:最大尾匹配;
  • %:从右往左;
  • \#:从左往右;
[root@localhost ~]# aaa=/d1/d2/d3/d4/my.test.txt
# 删除第一个/及其左边的内容(从左向右)
[root@localhost ~]# echo ${aaa#*/}
d1/d2/d3/d4/my.test.txt
# 删除最后一个/及其左边的内容
[root@localhost ~]# echo ${aaa##*/}
my.test.txt
# 删除第一个.及其左边的内容
[root@localhost ~]# echo ${aaa#*.}
test.txt
# 删除最后一个.及其左边的内容
[root@localhost ~]# echo ${aaa##*.}
txt
# 删除最后一个/及其右边的内容(从右向左)
[root@localhost ~]# echo ${aaa%/*}
/d1/d2/d3/d4
# 删除第一个/及其右边的内容
[root@localhost ~]# echo ${aaa%%/*}

# 删除最后一个.及其右边的内容
[root@localhost ~]# echo ${aaa%.*}
/d1/d2/d3/d4/my.test
# 删除第一个.及其右边的内容
[root@localhost ~]# echo ${aaa%%.*}
/d1/d2/d3/d4/my

7.3 $ [ ] 与$(( )) 整数运算

$ [ ] $(( )) 都是进行数学运算的,支持+ - * / %:分别为 “加、减、乘、除、取模”;需要注意的是,bash只能做整数运算,对于浮点数运算是当作字符串进行处理的;

[root@localhost ~]# a=5;b=7;c=2
[root@localhost ~]# echo $(( a+b+c ))
14
[root@localhost ~]# echo $(( a+b/c ))
8
[root@localhost ~]# echo $(( (a*b)%c ))
1
# 在 $(( )) 中的变量可以使用$符号也可以不使用;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Shell ❀ 基础变量类别与引用 的相关文章

  • vscode导入项目并启动

    不好意思图片不够清晰 我重新编辑一下文本信息 一 添加文件 打开vscode 如果之前没有添加过项目 可以点添加项目 也可以直接拖拽进去都是可以的 之前如果添加过 可以亦可以直接拖进去 但是只要项目之间互不干扰就可以 二 选择项目目录右键打
  • stm32f103c8移植Free RTOS遇到的bug和解决措施

    一 SVC系统调度错误 1 现象 xff1a 进入不了task 2 解决措施 xff1a xff08 1 xff09 将stm32f1xx it c里的void SVC Handler xff08 void xff09 函数给注释了 原因
  • FreeRTOS 实时内核实用指南之第一章任务管理知识总结

    任务函数顶层任务状态创建任务任务优先级扩充 非运行态 空闲任务与空闲任务钩子函数改变任务优先级删除任务调度算法 简述 一 任务函数 1 pvParameters 代表传入函数的参数 2 变量i和变量j 是在任务函数中的变量 xff0c 但是
  • 安装 kubectl

    以 Linux 为例 xff0c 两步 xff1a 1 下载 span class token function curl span span class token parameter variable LO span span clas
  • 关于单应性矩阵的若干思考

    1 名词解释 单应与射影变换是同义的 射影变换描述的是SE 2 到SE 2 的映射关系 映射与变换同义 映射h xff1a SE 2 到SE 2 是射影映射的充要条件是 xff1a 存在一个3x3非奇异矩阵H xff0c 使得任何一个用矢量
  • 自己的Docker Hub仓库 拉取镜像、推送镜像

    docker将本地镜像放入自己的Docker Hub仓库 首先到官网注册账号 xff1a https hub docker com 在本地Linux登录docker xff1a docker login 用户名 xff1a libowen1
  • 在gittee上建立远程仓库

    1 注册登录码云 xff0c 完善个人信息 2 设置本机绑定SSH公钥 xff0c 实现免密码登录 xff01 xff08 免密码登录 xff0c 这一步挺重要的 xff0c 码云是远程仓库 xff0c 我们是平时工作在本地仓库 xff01
  • 用windows自带WSL实现Ubuntu使用及ROS安装及gazebo黑屏解决

    Windows自带WSL实现Ubuntu使用 ROS安装 可视化桌面 gazebo黑屏解决 1 Ubuntu安装1 1 开放权限1 2 安装1 3 初始化 2 桌面环境配置2 1 换镜像源2 2 安装可视化桌面2 2 1 远程桌面连接 3
  • Optitrack视觉定位下基于ROS及PX4搭建四旋翼多机飞行平台

    Optitrack视觉定位下基于ROS及PX4搭建四旋翼多机飞行平台搭建 1 单机平台1 1 四旋翼硬件组装a 注意 1 2 机载板环境配置1 3 飞控参数配置a 注意 1 4 实飞全流程 2 多机通信2 1 多机ip地址存储2 2 ROS
  • Optitrack使用说明-基于ROS&vrpn实现的室内定位

    Optitrack使用说明 基于ROS amp vrpn实现的室内定位 待续
  • C语言实现http请求器

    C语言实现http请求器 项目介绍 本项目完成一个http客户端请求器 xff0c 该请求器往服务器发送请求 xff0c 并接受服务器发来的响应数据 程序执行流程 建立TCP连接在TCP连接获得的socket的基础上 xff0c 发送htt
  • 【 ROS 软件包 】ROS安装软件包的两种方法

    使用apt安装 xff0c 安装在 opt ros melodic share目录下 xff1a sudo apt span class token operator span get install ros span class toke
  • 【 PID 算法 】PID 算法基础

    前言 xff1a 这两天打算找个实习 xff0c 奈何感觉自己有点菜 xff0c 所以 xff0c 就补习了一下知识 xff0c 说一下 xff0c 这个PID算法吧 一 简介 PID即 xff1a Proportional xff08 比
  • 7、OPencv 图形轮廓检测

    要想实现轮廓检测 xff0c 首先我们需要对待检测的图像进行图像处理 xff1a 图像灰度化 高斯滤波 Canny 边缘检测 边缘检测放大处理 提取轮廓 一 实现简单的全图型检测 即只要将drawContours第三个参数设置为 1 既能实
  • Spring Boot 接口统一前缀

    需求 需求如题 xff0c 想给一个 spring boot 项目的所有请求路径添加统一前缀 xff0c 可以通过 context path 来配置 但是在同时存在静态资源和 Controller 接口的项目中 xff0c 如果希望静态资源
  • 一文读懂pid控制器

    文章目录 PID控制器1 控制器1 1 电机速度控制系统1 2 温度或水位控制系统1 3 小小总结 2 PID3 模拟式PID4 数字式PID4 1 位置式PID算法4 1 2 位置式pid算法的缺点 4 2 增量式PID算法4 2 2 增
  • Gazebo创建围墙并生成.world文件

    Gazebo创建围墙并生成 world仿真环境文件 文件说明 world文件是gazebo中搭建的仿真环境保存后的文件格式 xff0c 其中包含了若干个模型文件 world文件如图所示 xff1a 其中相关参数是gazebo基于我们在gaz
  • Ubuntu18.04分区方案

    由于Ubluntu18 04安装和16 04基本一样 xff0c 因此就没什么好说的 xff0c 主要记录一下分区方案 硬盘总容量 xff1a 500G 分区方案 xff1a EFI分区 逻辑分区 xff0c 空间起始位置 xff0c 10
  • Ubuntu18.04搭建AirSim+ROS仿真环境

    AIRSIM在UBuntu 18 04上构建的官网文档 一 安装UE4引擎 AIRSIM是依赖于UE4引擎实现的 因此在安装AIRSIM之前要安装UE4引擎 1 获取UE4的github许可 在Ubuntu上安装UE4引擎需要从源文件进行编
  • OpenCV-Python学习笔记(使用opencv识别物体的位置,找到中心点位)

    使用opencv识别物体的位置 xff0c 找到中心点位 xff1a 步骤 xff1a 先拿到图像 gt 进行高斯滤波 gt 进行灰度处理 gt 进行二值化 gt 进行开运算 gt 轮廓提取 gt 计算中心点位 效果图如下 xff1a 代码

随机推荐

  • ROS下使用realsense-d435i跑通 rgbdslam_v2运行踩坑完成

    准备工作 rbgdslam v2 按照github 实验环境Ubuntu 16 04 ROS kinetic 如果你电脑安装PCL版本是1 7 xff0c 那么请直接跳到错误1 xff0c 如果你也不知道有没有 xff0c 或者版本多少 x
  • ROS学习 catkin CMakeList.txt详细介绍

    ROS中catkin CMakeLists txt的内容 CMakeList txt文件是CMake编译系统编译软件包过程的输入文件 任何CMake兼容包都包含一个或多个CMakeLists txt文件 xff0c 这些文件描述了如何编译代
  • ROS Catkin 教程之 CMakeLists.txt

    1 概览 CMakeLists txt 是用 CMake 构建系统构建 ROS 程序包的输入文件 任何兼容 CMake 的包都包含一个或多个 CMakeLists txt 文件 xff0c 用以描述怎样构建和安装代码 catkin 项目采用
  • ROS在roslaunch时,提示“is neither a launch file in package”或TAB时没有补全

    描述 已经设置了source devel setup bash xff0c 在同一终端用roslaunch可以 xff0c 但我在这个终端起的是roscore xff0c 新终端再用roslaunch就不行了 分析 报错是因为没找到对应的p
  • ros绑定串口

    本文主要介绍ros绑定串口设备的一种方法 1 检查有多少个设备 span class token function ls span dev ttyUSB 2 查看对应串口 查看KERNELS后面的设备的硬件端口号 udevadm info
  • Spring Boot 配置文件配置自动提示 Configuration Processor

    效果 在使用Idea等开发工具时 xff0c 配置文件中输入前缀就有对应的补全提示 xff0c 使开发者可以很方便配置相应属性 xff0c 效果截图如下 xff1a 元数据说明 这些提示来自于 spring 自动配置规范中的源数据文件 sp
  • ubuntu20.4安装python3.8

    ubuntu20 4中安装python3 8 注 ubuntu20 4自带python3 10 软连接python3与pip3指向的为python3 10本文意在安装python3 8 并将软连接python与pip指向python3 8
  • C/C++多线程、线程同步(互斥锁与信号量)

    参考链接2 中写的非常好 xff0c 简单易懂 xff0c 上手快 xff0c 非常好的博文 使用多线程及互斥锁样例 xff1a include lt iostream gt include lt windows h gt using na
  • Python ❀ 初学者学习笔记与知识点梳理

    软件安装与环境部署变量与数据类型列表与元组条件判断语句字典while循环函数类文件与异常 推荐代码练习地址 xff1a https www runoob com python python 100 examples html 点击此处直接跳
  • Shell ❀ Linux系统自动挂载本地yum源并安装rpm依赖包

    文章目录 1 脚本代码详解2 代码执行结果3 脚本参数调整 1 脚本代码详解 span class token comment bin bash span span class token builtin class name echo s
  • Windows ❀ Windows系统下端口连通性常见的验证方法

    文章目录 1 telnet1 1 telnet服务开启方法1 2 端口连通性验证 2 tcping2 1 tcping下载与安装2 2 端口连通性验证 3 netstat ano findstr3 1 findstr使用语法3 2 端口连通
  • Security ❀ 安全设备学习规范(第二版)

    文章目录 安全设备学习规范1 设备部署环境1 1 部署方式1 2 配置IP地址与路由1 3 设备冗余机制1 4 会话同步机制1 5 设备账户管理1 6 设备故障诊断 2 产品授权方式2 1 序列号2 2 Hash值 3 相关设备联动3 1
  • Windows ❀ 解决Google浏览器无法访问网页问题

    文章目录 问题 xff1a Google浏览器无法访问网页解决方法 问题 xff1a Google浏览器无法访问网页 使用Google浏览器打开某个已知安全网页时 xff0c 弹出如下信息 xff0c 错误内容如下 xff1a NET ER
  • Security ❀ CSP Bypass 内容安全策略绕过

    文章目录 内容安全策略绕过 CSP Bypass1 Low Level2 Medium Level3 High Level4 Impossible Level 内容安全策略绕过 CSP Bypass CSP 内容安全策略 xff1a 为了缓
  • Security ❀ JavaScript Attacks 前端攻击

    文章目录 JavaScript Attacks 前端攻击1 Low Level2 Medium Level3 High Level4 Impossible Level JavaScript Attacks 前端攻击 JavaScript是一
  • MiddleWare ❀ Zookeeper基础概述

    文章目录 1 认识Zookeeper1 1 数据类型1 2 监听器1 3 基本功能1 3 1 统一配置管理1 3 2 统一命名服务1 3 3 分布式锁1 3 4 集群状态 2 下载安装包3 安装服务3 1 服务端命令3 2 客户端命令 3
  • Java文件内容变更及内容追加监听方案

    简介 对于文件内容变动的监听处理 xff0c 一般分为两种主要应用场景 1 只关心文件内容是否发生变更 文件的内容发生变动的场景是全量修改模式 xff0c 不是内容追加模式 例如某xml文件内容发生变动 这种情况 xff0c 我们一般只需要
  • MiddleWare ❀ MySQL基础概述

    文章目录 MySQL基础1 SQL语法与分类1 1 DDL 数据定义语言1 1 1 库操作1 1 1 1 查询1 1 1 2 创建1 1 1 3 删除1 1 1 4 使用 1 1 2 表 43 字段操作1 1 2 1 查询1 1 2 2 创
  • Shell ❀ 基础知识概述

    文章目录 一 基本概念1 脚本文件命名方式2 解释器分类3 基本基本组成内容4 脚本编写规范与格式说明5 自动生成脚本的注释与配置信息 一 基本概念 shell又称为命令解释器 xff0c 它能识别用户输入的各种命令 xff0c 并传递给操
  • Shell ❀ 基础变量类别与引用

    文章目录 二 变量与引用1 变量命名2 变量类型3 变量定义4 常用变量4 1 内置通配符4 2 内置变量4 3 自定义变量4 4 环境变量4 5 变量的作用域4 5 1 全局变量4 5 2 局部变量 4 6 位置变量4 5 1 位置变量的