目录

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

功能:

  • 定义命令别名和函数
  • 定义本地变量编辑配置文件生效