shell 变量、字符串的处理方法

2023-12-21 08:52:21

简介

? ? 字符串是由一个或多个字符组成的数据类型。在编程中,字符串常用于存储和处理文本数据,可以使用单引号(’ ')或双引号(" ")括起来。

??????

目录

1. 字符串的基础

1.1. 字符串引号的区别

1.2. 如何在引号中输出引号

1.3. 使用引号赋值变量

2. 字符串变量的高级用法

2.1. 按索引截取字符串

2.2. 按分隔符截取字符串

2.3. 判断变量是否存在

2.4. 转换字母大小写

2.5. 替换字符


????????

1. 字符串的基础

1.1. 字符串引号的区别

在学习处理字符串方法之前,需要了解一些基本知识。比如我们平时在写代码时,一般不区分单引号、双引号,但在 shell 中,单引号和双引号在解释上有一些区别,先来看一个例子:

使用 echo 分别使用单引号和双引号输出字符串,这里看起来是一样的。

????????

我们来看下一个例子,输出变量

这时可以发现使用单引号,里面是什么字符就输出什么字符;使用双引号则可以进行变量替换。所以两种引号有这么一些区分:

  1. 单引号不会解释特殊符号,会直接按字面输出;
  2. 双引号可以解释特殊符号,包括:变量${ }、命令$( )、命令` ` 等。

总结:如果需要输出带有特殊字符的纯文本,使用单引号最佳;如果需要输出某些变量时,使用双引号最佳。

????????

1.2. 如何在引号中输出引号

在了解了单引号和双引号的区别后,那么下一个问题又来了,引号中怎么输出引号呢?这里列举了几种方式,懂得伙伴直接跳过。

????????

【案例一】单引号中输出单引号(目标 输出?id: 'a001' )

按我们平时思维,在引号中在放一个引号那么就可以输出,我们先来试试

echo 'id: 'a001' '

但是在 shell 的单引号字符串中,单引号字符被视为特殊字符,用于将字符串中的内容标记为一个整体。所以这种方式是不可行的(下图不符合预期)

在单引号字符串中使用转义字符 \ 来表示单引号字符本身,即 \' 表示一个单引号字符。所以正确的使用方法是?'\'' ,来看一下例子

echo 'id: '\''a001'\'' '

符合预期

????????

【案例二】单引号中输出双引号(目标 输出?id: "a001" )

单引号中嵌套双引号是可以正常使用的

echo 'id: "a001" '

????????

【案例三】双引号中输出单引号(目标 输出?id: 'a001' )

双引号中嵌套单引号也是正常的

echo "id: 'a001' "

????????

【案例四】双引号中输出双引号(目标 输出?id: "a001" )

与《案例一》不同的是,双引号中支持各种转义符,所以我们直接对双引号进行转义即可

echo "id: \"a001\" "

????????

【案例五】输出嵌套引号(目标 输出?id: "a001: 'a001.1: "b001" ' " )

echo "id: \"a001: 'a001.1: \"b001\" ' \" "

这条命令看起来老壳疼,实际上理解了就很简单。我们知道,在双引号中是可以使用单引号的,如果在双引号中使用双引号那么需要使用转义符 \" ,说到这里再看一眼命令就明白了。

????????

1.3. 使用引号赋值变量

前面讲了不同引号的区别和引号中包含引号,这其实也是与赋值给变量有关系的。比如给变量赋值另一个变量的结果(引号的方式是一样的)

v1="AAA"
v2="BBB ${v1}"

????????

给变量赋值一个命令的执行结果

v1="AAA $(ls)"

如果 v1 已经赋值,删除当前路径下的某个文件,v1 的值也不会发生变化

????????

变量的长度也是通过 ${#变量} 获取(空格也算一个字符)

?????????

2. 字符串变量的高级用法

2.1. 按索引截取字符串

我们平时定义一个变量为 v='abc',在使用这个变量时通过 $ 符号 + 变量名,2种方式:

写法一:$v
写法二:${v}

这两种方式都可以,大部分人使用第1种方法(估计是为了少写两个字符),实际上标准写法是第2种。用《写法一》举1个简单的例子来看它的缺点:

目标:输出变量 v 和字符串 123?的组合

见上图,我们使用第1种方法,没有带花括号,那么被识别为变量 v123,所以出错了。如果我们带上花括号就不会出现这种情况

????????

除了变量之外,我们在使用索引时,也是必须使用花括号的。语法如下:

${变量名:开始索引下标:次数}

shell 中的索引没有跳跃式匹配,只能指定索引下标和后面字符数。有两个匹配方法:

# 从左往右匹配前面字符
${v:1}
# 从右往左匹配后面字符,负数需要使用括号
${v:(-1)}

注意:索引是从0开始,所以第1个字符的下标是0,比如匹配下标为0的一个字符和下标为1的一个字符

v='abcdefghji'
echo ${v:0:1}    # 0表示从下标0开始,1表示只匹配1个字符
echo ${v:1:1}    # 前面的1表示从下标1开始,后面的1表示只匹配1个字符

字符:a b c d e f g h j i
下标:0 1 2 3 4 5 6 7 8 9

因为只能指定索引下标的开始的次数,所以总结了以下几种方法

????????

【案例一】获取第3个字符后面的全部字符

${v:2}    # 第3个字符的下标为2

????????

【案例二】获取第3个字符后面的2个字符

${v:2:2}    # 第3个字符的下标为2,再指定2个字符

????????

【案例三】获取最后5个字符

${v:(-5)}    # -5表示后面的5个字符
${v:(-2-3)}  # 两种方法是一样的

????????

【案例四】获取后面5个字符的前面2个

${v:(-5):2}    # -5表示后面的5个字符,2表示从左往右前2个字符

????????

总结

虽然看起来方法很少,但实际上我们想要的基本都可以做到。比如:

读取前面3个字符:${v:0:2}

读取后面3个字符:${v:(-3)}

读取中间第3~5个字符:${v:2:3}

????????

2.2. 按分隔符截取字符串

除了字符串常见的用法外,我们来看一下这里面的一些骚操作:先来看几个符号的解释

# :从左往右匹配第一个指定的字符,删除最前面~匹配字符
##:从右往左匹配第一个指定的字符,删除最前面~匹配字符
% :从右往左匹配第一个指定的字符,删除最后面~匹配字符
%%:从左往右匹配第一个指定的字符,删除最后面~匹配字符
* : 通配符

????????

【# 例子】从左往右匹配第一个字符 / ,删除前面的值

v=/home/yt/tmp/file
${v#*/}    # 删除 / 到最前面
${v#*yt}   # 删除 yt 到最前面
${v#*m}    # 变量中有2个m,匹配模式是从左往右,所以删除的是 /hom

这个例子对路径可能不太合适,如果是匹配文件的后缀就很好用了

v="file.txt"
${v#*.}

????????

【## 例子】从右往左匹配第一个字符 / ,删除前面的值

v=/home/yt/tmp/file
${v##*/}    # 删除最后一个 / 到最前面
${v##*tmp}  # 删除 tmp 到最前面

一个 # 号获取后缀只适用于只有一个文件名,如果存在多个点还是使用 ## 更合适

????????

【%?例子】从右往左匹配第一个字符 / ,删除后面的值

v=/home/yt/tmp/file
${v%/*}    # 删除 / 到最后面
${v%yt*}   # 删除 yt 到最后面
${v%m*}    # 变量中有2个m,匹配模式是从右往左,所以删除的是 mp/file

????????

【%% 例子】从左往右匹配第一个字符 / ,删除后面的值

v=/home/yt/tmp/file
${v%%/*}    # 删除最后一个 / 到最后面
${v%%yt*}   # 删除 yt 到最后面
${v%%m*}    # 变量中有2个m,匹配模式是从左往右,所以删除的是 me/yt/tmp/file

????????

总结

以 . 为分隔符,不显示第1列:v=192.168.20.80

  • ${v#*.}? ? #168.20.80

以 / 或 . 为分割符,查询路径最后一个文件名或后缀名:v=/home/yt/tmp/file.txt

  • ${v##*/}? ? # file.txt
  • ${v##*.}? ? # txt

以 / 为分隔符,显示某个文件的路径:v=/home/yt/tmp/file.txt

  • ${v%/*}? ? #?/home/yt/tmp

以 . 为分隔符,只显示第1列:v=192.168.20.80

  • ${v%%.*}? ? #?192

????????

2.3. 判断变量是否存在

《目录2.2》描述了通过 # 和 % 符号指定分隔符,那么还有一些其他的符号,比如冒号

【案例一】如果不存在变量或变量为空,则返回xxx(自定义输出)

${v:-'自定义输出'}

判断变量是否为空,如果存在一个空格也不为空

????????

【案例二】如果变量不存在或为空,则指定一个默认值

${v:='默认值'}

????????

【案例三】如果变量为空则退出程序

${v:?'变量为空,退出程序'}

????????

2.4. 转换字母大小写

${v^} :转换变量v首字母为大写
${v^^}:转换变量v所有字母为大写
${v,} :转换变量v首字母为小写
${v,,}:转换变量v所有字母为小写

【案例一】转换首字母为大写、全部字母为大写

????????

【案例二】转换首字母为小写、全部字母为小写

????????

2.5. 替换字符

${变量/旧字符/新字符}

?????????

【案例一】将变量中 b 全部替换为 i(注意:需要两个 / 符合)

${变量//b/i}

????????

【案例二】将变量中第1个 b 替换为 i(注意:使用一个 / 符号)

${变量/b/i}

????????

【案例三】将以 ab 开头的 ab 替换为 i(注意:使用 # 符号)

${变量/#ab/i}

????????

【案例四】将以 bc 结尾的 bc 替换为 i(注意:使用符号 %)

${变量/%bc/i}

文章来源:https://blog.csdn.net/m0_61066945/article/details/135104238
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。