Linux-入门到精通,真的不用背命令零基础小白靠场景化学习法,3-个月拿下运维-offer,第二十六天
Linux 入门到精通,真的不用背命令!零基础小白靠「场景化学习法」,3 个月拿下运维 offer,第二十六天
Shell脚本编程
字符串详解
字符串(String)是Shell编程中最常用的数据类型之一,表示一系列字符的组合。在Shell中,字符串可以通过三种方式表示:单引号包围、双引号包围以及不使用引号。
单引号字符串(’ ‘)
- 所有字符都会原样输出,变量不会被解析
- 字符串内部不能包含单引号,即使转义也不可行
双引号字符串(" “)
- 包含的变量会被解析为实际值
- 可以包含双引号,但需要用转义字符处理
无引号字符串
- 变量会被解析(与双引号字符串相同)
- 不能包含空格,否则空格后的内容会被识别为其他变量或命令
通过代码演示一下三种形式的区别
#!/bin/bash
n=74
str1=c.biancheng.net$n
str2="shell \"Script\" $n"
str3='C语言中文网 $n'
echo $str1
echo $str2
echo $str3
# 运行结果
c.biancheng.net74
shell "Script" 74
C语言中文网 $n
在字符串str1中, n这个符号被识别为变量n的引用。紧跟在n这个符号被识别为变量n的引用。紧跟在 n之后的空格后再出现str2,Shell会将其视作一个新的变量名,而不会把它当作字符串str1的一部分。字符串str2中包含引号,但这些引号被转义了(在Shell中,反斜杠\用来表示转义字符)。此外,str2中也包含了 n,同样被解析为变量n的引用。而在str3中,虽然也出现了n,同样被解析为变量n的引用。而在str3中,虽然也出现了 n,但它仅被视为普通字符,并未被解析为变量n的引用。
在Shell中,获取字符串的长度非常简单,具体方法如下:
${#string_name}
string_name:表示字符串名字
Shell字符串拼接
在脚本语言中,字符串的拼接(也称为字符串连接或者字符串合并)往往都非常简单,例如:在PHP中使用.
即可连接两个字符串,在JavaScript中使用+
即可将两个字符串合并为一个。然而,在Shell中,你不需要使用任何运算符,将两个字符串并排放在一起就能实现拼接。这种简便的方法使得Shell在处理字符串时非常高效。
Shell字符串拼接的实用性体现在多个方面。首先,它简化了脚本的编写,使得开发者能够更快速地组合和操作字符串。其次,这种拼接方式在处理变量和常量时同样适用,增加了脚本的灵活性。举例来说,假设你有一个存储路径的变量和一个存储文件名的变量,你可以轻松地将它们拼接起来形成一个完整的文件路径,而无需使用额外的运算符或函数。
#!/bin/bash
name="shell"
url="http://c.biancheng.net/shell/"
str1=$name$url #中间不能有空格
str1=$name":"$url
str2="$name $url" #如果被双引号包围,那么中间可以有空格,也可以出现别的字符串
str3="$name:$url"
str4="${name}Script:${url}Index.html" #在变量后加上字符串,需要给变量名加上大括号
Shell字符串截取技巧
在Shell中,截取字符串通常有两种主要方式:从指定位置开始截取和从指定字符(或子字符串)开始截取。
从指定位置开始截取:
这种方式需要指定两个参数:起始位置和截取长度,才能确定最终要截取的字符串。由于需要指定起始位置,这就引出了一个问题:计数方向到底是“从左到右”还是“从右到左”?实际上,Shell同时支持这两种计数方式。
从字符串左边开始计数:
如果选择从字符串的左边开始计数,那么截取字符串的具体格式如下:
${string:start:length}
`其中,Sting是要截取的字符串,start是起始位置(从左边开始,从0开始计数),length是要截取的长度(省略的话表示直到字符串的末尾)
例如:
url="c.biancheng.net"
echo ${url:2:9}
>结果为:biancheng
url="c.biancheng.net"
echo ${url:2} #省略length,截取到字符串末尾
>结果为:biancheng.net
从右边开始计数
如果想从字符串的右边开始计数,那么截取字符串的具体格式如下:
${string:0-start:length}
`同第 1) 种格式相比,第 2) 种格式仅仅多了0-,这是固定的写法,专门用来表示从字符串右边开始计数。
这里需要强调两点:
从左边开始计数时,起始数字是 0(这符合程序员思维);
从右边开始计数时,起始数字是 1(这符合常人思维)
计数方向不同,起始数字也不同。
不管从哪边开始计数,截取方向都是从左到右。
例如:
url="c.biancheng.net"
echo ${url:0-13:9}
>结果为:biancheng 从右边数:b是第13个字符
url="c.biancheng.net"
echo ${url:0-13} #省略length,直接截取到字符串末尾
>结果为:biancheng.net
从指定字符(子字符串)开始进行字符串截取时,由于无法预先确定截取的长度,所以截取操作会一直持续到字符串的末尾。Shell提供了灵活的截取功能,不仅可以截取指定字符(子字符串)右侧的所有字符,还能截取左侧的所有字符。
使用#号截取右侧字符:
通过使用#号,我们可以截取从指定字符(或子字符串)右侧开始的所有字符。
具体格式如下:
${string#*chars}
#其中,string 表示要截取的字符,chars 是指定的字符(或者子字符串),*是通配符的一种,表示任意长度的字符串。*chars连起来使用的意思是:忽略左边的所有字符,直到遇见 chars(chars 不会被截取)
例如:
url="http://c.biancheng.net/index.html"
echo ${url#*:}
>结果为://c.biancheng.net/index.html
echo ${url#*p:}
echo ${url#*ttp:}
`如果不需要忽略chars左边的字符,那么也可以不写*
url="http://c.biancheng.net/index.html"
echo ${url#http://}
>结果为:c.biancheng.net/index.html
`注意:以上写法遇到第一个匹配的字符(子字符串)就结束了
url="http://c.biancheng.net/index.html"
echo ${url#*/}
>结果为:/c.biancheng.net/index.html。url 字符串中有三个/,输出结果表明,Shell 遇到第一个/就匹配结束了
使用##
可以直到最后一个指定字符(子字符串)再匹配结束
${string##*chars}
例如:
#!/bin/bash
url="http://c.biancheng.net/index.html"
echo ${url#*/}
# 结果为:/c.biancheng.net/index.html
echo ${url##*/}
# 结果为:index.html
str="-----aa+++aa@@@"
echo ${str#*aa}
# 结果为:+++aa@@@
echo ${str##*aa}
# 结果为:@@@
使用%截取左边字符
使用%
号可以截取指定字符(或者子字符串)左边的所有字符
${string%chars*}
`请注意*的位置,因为要截取 chars 左边的字符,而忽略 chars 右边的字符,所以*应该位于 chars 的右侧。其他方面%和#的用法相同
#!/bin/bash
url="http://c.biancheng.net/index.html"
echo ${url%/*} #结果为 http://c.biancheng.net
echo ${url%%/*} #结果为 http:
str="---aa+++aa@@@"
echo ${str%aa*} #结果为 ---aa+++
echo ${str%%aa*} #结果为 ---
汇总
Shell的格式化输出printf
语法格式:
printf "指定的格式" "文本1" "文本2" .....
常用格式替换符:
说明:%s中的数字代表此替换符中的输出字符宽度,不足补空格,默认是右对齐,%-10s表示10个字符宽,-表示左对齐
常用转义字符:
例如
[root@localhost ~]# printf "%s\n" 1 2 3 4
1
2
3
4
[root@localhost ~]# printf "%f\n" 1 2 3 4
1.000000
2.000000
3.000000
4.000000
[root@localhost ~]# printf "%.2f\n" 1 2 3 4 #.2f表示保留两位小数
1.00
2.00
3.00
4.00
[root@localhost ~]# printf "(%s)" 1 2 3 4;echo " "
(1)(2)(3)(4)
[root@localhost ~]# printf " (%s) " 1 2 3 4;echo " "
(1) (2) (3) (4)
[root@localhost ~]# printf " (%s) (%s)\n" 1 2 3 4;echo " "
(1) (2)
(3) (4)
[root@localhost ~]# printf " %s %s\n" 1 2 3 4;echo " "
1 2
3 4
[root@localhost ~]# printf "%s %s %s\n" 1 2 3 4
1 2 3
4
[root@localhost ~]#
#%-10s表示宽度10个字符,左对齐
[root@localhost ~]# printf "%-10s %-10s %-4s %s \n" 姓名 性别 年龄 体重 小明 男性 20岁 70KG 小红 女性 18岁 50KG
姓名 性别 年龄 体重
小明 男性 20岁 70KG
小红 女性 18岁 50KG
[root@localhost ~]#
#将十进制的1000转换为16进制数
[root@localhost ~]# printf "%X\n" 1000
3E8
[root@localhost ~]# printf "%x\n" 1000
3e8
[root@localhost ~]#
#将十六进制的C转换为十进制
[root@localhost ~]# printf "%d\n" 0xc
12
[root@localhost ~]#
[root@localhost ~]# var="welcome to study";printf "\033[31m%s\033[0m\n" $var
welcome
to
study
[root@localhost ~]# var="welcome to study";printf "\033[31m%s\033[0m\n" "$var"
welcome to study
[root@localhost ~]#
bash的配置文件
bash shell的配置文件很多,可以分为以下类别
按生效范围划分为两类
全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
个人配置
~/.bash_profile
~/.bashrc
shell登录的两种方式分类
交互式登录
- 直接通过终端输入账户密码
- 使用
su - username
切换用户
配置文件执行顺序:
/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
非交互式登录
- su username
- 图形界面下打开的终端
- 执行脚本
- 任何其他的bash实例
配置文件执行顺序:
/etc/profile.d/*.sh --> /etc/bashrc --> ~/.bashrc
按功能划分分类
Profile类
profile类为交互式登录的shell提供配置
全局:/etc/profile, /etc/profile.d/*.sh
个人:~/.bash_profile
功能:
用于定义环境变量
运行命令或脚本
Bashrc类
bashrc类:为非交互式和交互式登录的shell提供配置
- 全局:
/etc/bashrc
- 个人:
~/.bashrc
功能:
- 定义命令别名和函数
- 定义本地变量编辑配置文件生效