# shell中常用的变量处理、字符串操作（之三）

- 7

- A+

所属分类：Shell 编程

之前的文章中，我们提到了shell中常用的字符串处理操作，我们来回顾一下

一、获取变量的长度（字符串长度）。

二、对变量值进行截取（截取字符串）。

三、替换变量值中的某段字符。

四、删除变量值中的某段字符。

五、对变量值进行大小写转换。

六、当变量值为空时，对变量进行一些操作。

前两篇文章中，我们已经总结了上述操作中的前四种操作，今天，我们来介绍一下上述操作的最后两种操作，并将之前的所有总结进行一个汇总，以便以后进行回顾。

## 字符串大小写转换

首先，我们准备一个变量，变量值为字母a到z，只不过a到k为小写，L到Z为大写，如下图所示

如果我们想要将变量testvar1中的所有小写英文字母都转换成大写，该怎么办呢？我们可以使用如下方法。

如上图所示，只要在输出变量值时加上"^^"即可，"^"为数字键6对应的符号。

如果想要将变量testvar1中的所有大写英文字母都转换成小写，可以使用如下方法。

如上图所示，只要在输出变量值时加上",,"即可将字母中的大写字符转换成小写，很简单吧~

## 当变量值为空或者非空时对变量进行操作

在写shell脚本时，我们可能会遇到如下场景。

我们需要判断某个变量是否为空，如果变量值不为空，则使用变量当前的值，如果为空，则赋予变量一个默认值，以便之后进行处理。

那么，在脚本中可能会出现类似如下代码

if [ -z "$testvar" ];then

testvar="test"

fi

如上述代码所示，我们使用 if 结构，判断了变量testvar是否为空，如果为空，则将变量赋值为test，当然，如果变量值不为空，那么则不会被赋值，即保持变量原值不变。

其实，我们可以使用更简单的方法，我们只需要一行代码，就可以代替上例中的三行代码，示例如下

${testvar:="test"}

没错，就是这么简单，上述代码表示，如果变量testvar的值为空，则将testvar赋值为test，如果不为空，则testvar保持原值不变。我们在命令行中试试上述代码的效果，首先，将变量testvar的值设置为空值，然后使用上述语法，如下。

可以看到，当变量为空时，上述语法不仅会将变量的值设置为指定值，同时还会返回对应的值，我们可以直接使用echo命令进行输出，经过上述语法处理后，再次输出变量，变量已经被赋值。

当变量值不为空时，经过上述语法处理后，只会返回变量的原值，并不会改变变量的值，示例如下

可以发现，当变量为空时，使用上述语法会返回我们指定的值，同时还会将变量设定为我们指定的值，其实，还有另外一种方法，能够在变量为空时返回我们指定的值，但是不对变量进行赋值，示例如下。

${testvar:-"test"}

细心如你一定发现了，与之前的语法相比，只是语法中的"="替换成了"-"

上述语法表示，如果testvar变量值为空，则返回指定的文本"test"，如果testvar变量值不为空，则返回testvar变量本身的值，但是，当testvar变量值为空时，使用上述语法，只会返回指定的值，并不会对变量进行赋值操作，我们在命令行中看一下效果，示例如下。

可以看到，当变量为空时，上述语法并不会对变量赋值，当变量值不为空时，示例如下。

之前的两个示例，都是在变量为空时，返回我们指定的值，那么能不能在变量不为空时，返回我们指定的值呢？必须能的，使用如下语法即可。

${testvar:+"test"}

上述语法表示，当testvar变量值不为空时，返回指定的字符串"test"，如果变量为空，则返回变量本身的值（即空值），示例如下

如上图所示，当变量值不为空时，使用上述语法会返回我们指定的值，但是并不会改变变量原来的值，如果变量值为空，使用上述语法，仍然返回空值，同时也不会对变量进行赋值。

我们还可以在变量为空时，输出bash风格的error_info，示例如下

${testvar:?"error_info"}

上述语法表示testvar变量为空时，输出bash错误，错误信息为我们指定的字符串error_info

示例如下

## 总结

为了方便以后回顾，我们将之前所有与字符串处理、变量处理的相关操作进行汇总，并进行一个总结。

### 获取字符串长度

Shell
# testvar="12345" # echo ${#testvar} 5

1 2 3 | # testvar="12345" # echo ${#testvar} 5

### 对变量值进行大小写转换

将变量值中的小写字母装换为大写

语法：echo ${var^^}

Shell
#示例 # testvar="case conversion" # echo ${testvar} case conversion # echo ${testvar^^} CASE CONVERSION

1 2 3 4 5 6 | #示例 # testvar="case conversion" # echo ${testvar} case conversion # echo ${testvar^^} CASE CONVERSION

将变量值中的小写字母装换为大写

语法：echo ${var^^}

Shell
#示例 # testvar="CASE CONVERSION" # echo ${testvar} CASE CONVERSION # echo ${testvar,,} case conversion

1 2 3 4 5 6 | #示例 # testvar="CASE CONVERSION" # echo ${testvar} CASE CONVERSION # echo ${testvar,,} case conversion

### 当变量值为空或者非空时操作变量

${var:=value}

上述语法表示如果var为空，则返回value，并将value赋值给var，如果var不为空，则返回var本身的值，var不为空时，var值不会被改变，var为空时，var的值会被设置成指定值。

${var:-value}

上述语法表示如果var为空，则返回value，如果var不为空，则返回var的值，无论var是否为空，var本身的值不会改变。

${var:+value}

上述语法表示如果var不为空，则返回value，如果var为空，则返回空值，无论var是否为空，var本身的值不会改变。

${var:?error_info}

上述语法表示如果var为空，那么在当前终端打印error_info，如果var的值不为空，则返回var的值，无论var是否为空，var本身的值都不会改变。

### 从指定位置截取字符串，截取到字符串的末尾

#下例表示从正数第4个字符以后开始截取，直到字符串的末尾。

Shell
# website="www.zsythink.net" # echo ${website:4} zsythink.net

1 2 3 | # website="www.zsythink.net" # echo ${website:4} zsythink.net

#下例表示从倒数第4个字符开始截取，直到字符串的末尾

#注意：下例中的"负号"与"冒号"之间必须存在任意字符（通常使用0或空格占位），否则无法起到截取字符串的作用。

Shell
# website="www.zsythink.net" # echo ${website:0-4} .net # echo ${website: -4} .net # echo ${website:a-4} .net

1 2 3 4 5 6 7 | # website="www.zsythink.net" # echo ${website:0-4} .net # echo ${website: -4} .net # echo ${website:a-4} .net

### 从指定位置截取字符串，并且截取指定的长度

#下例表示从正数第4个字符以后开始截取，截取8个字符。

Shell
# website="www.zsythink.net" # echo ${website:4:8} zsythink

1 2 3 | # website="www.zsythink.net" # echo ${website:4:8} zsythink

#下例表示从倒数第9个字符开始截取，截取5个字符。

Shell
# website="www.zsythink.net" # echo ${website:0-9:5} think

1 2 3 | # website="www.zsythink.net" # echo ${website:0-9:5} think

##centos7中，截取长度可以为负数，centos6中不行，centos7中的示例如下

#下例表示从正数第4个字符以后开始截取，截取到字符串的末尾，再将截取后的字符串的最后3个字符删除。

Shell
# website="www.zsythink.net" # echo ${website:4:-3} zsythink.

1 2 3 | # website="www.zsythink.net" # echo ${website:4:-3} zsythink.

##centos7中，截取长度可以为负数，centos6中不行，centos7中的示例如下

#下例表示从倒数第4个字符开始截取，截取到字符串的末尾，再将截取后的字符串的最后1个字符删除。

Shell
# website="www.zsythink.net" # echo ${website:0-4:-1} .ne

1 2 3 | # website="www.zsythink.net" # echo ${website:0-4:-1} .ne

### 掐头去尾截取之掐头截取

掐头截取：删除字符串中从左向右第一个遇到的char，以及其左侧的字符

##语法：${var#*char}

Shell
#下例表示删除字符串中从左向右第一个遇到的 "." ，以及其左侧的字符。 # website="www.zsythink.net" # echo ${website#*.} zsythink.net #下例表示删除字符串中从左向右第一个遇到的 "//" ，以及其左侧的字符。 # website="https://ww.zsythink.net" # echo ${website#*//} ww.zsythink.net

1 2 3 4 5 6 7 8 9 | #下例表示删除字符串中从左向右第一个遇到的 "." ，以及其左侧的字符。 # website="www.zsythink.net" # echo ${website#*.} zsythink.net #下例表示删除字符串中从左向右第一个遇到的 "//" ，以及其左侧的字符。 # website="https://ww.zsythink.net" # echo ${website#*//} ww.zsythink.net

掐头截取：删除字符串中从左向右最后一个遇到的char，以及其左侧的字符

##语法：${var##*char}

Shell
#下例表示删除字符串中从左向右最后一个遇到的 "/" ，以及其左侧的字符。 # website="https://ww.zsythink.net/index.html" # echo ${website##*/} index.html #下例表示删除字符串中从左向右最后一个遇到的 "." ，以及其左侧的字符。 # website="www.zsythink.net" # echo ${website##*.} net

1 2 3 4 5 6 7 8 9 | #下例表示删除字符串中从左向右最后一个遇到的 "/" ，以及其左侧的字符。 # website="https://ww.zsythink.net/index.html" # echo ${website##*/} index.html #下例表示删除字符串中从左向右最后一个遇到的 "." ，以及其左侧的字符。 # website="www.zsythink.net" # echo ${website##*.} net

### 掐头去尾截取之去尾截取

去尾截取：删除字符串中从右向左第一个遇到的char，以及其右侧的字符

##语法：${var%char*}

Shell
#下例表示删除字符串中从右向左第一个遇到的 "/" ，以及其右侧的字符。 # testpath="/usr/local/nginx/conf.d" # echo ${testpath%/*} /usr/local/nginx #下例表示删除字符串中从右向左第一个遇到的 "@" ，以及其右侧的字符。 # testmail="zsy@zsythink.net" # echo ${testmail%@*} zsy

1 2 3 4 5 6 7 8 9 | #下例表示删除字符串中从右向左第一个遇到的 "/" ，以及其右侧的字符。 # testpath="/usr/local/nginx/conf.d" # echo ${testpath%/*} /usr/local/nginx #下例表示删除字符串中从右向左第一个遇到的 "@" ，以及其右侧的字符。 # testmail="zsy@zsythink.net" # echo ${testmail%@*} zsy

去尾截取：删除字符串中从右向左最后一个遇到的char，以及其右侧的字符

##语法：${var%%char*}

Shell
#下例表示删除字符串中从右向左最后一个遇到的 "/" ，以及其右侧的字符。 # website="https://ww.zsythink.net/index.html" # echo ${website%%/*} https: #下例表示删除字符串中从右向左最后一个遇到的 ":" ，以及其右侧的字符。 # testpasswd="root:x:0:0:root:/root:/bin/bash" # echo ${testpasswd%%:*} root

1 2 3 4 5 6 7 8 9 | #下例表示删除字符串中从右向左最后一个遇到的 "/" ，以及其右侧的字符。 # website="https://ww.zsythink.net/index.html" # echo ${website%%/*} https: #下例表示删除字符串中从右向左最后一个遇到的 ":" ，以及其右侧的字符。 # testpasswd="root:x:0:0:root:/root:/bin/bash" # echo ${testpasswd%%:*} root

### 删除字符串的操作

删除变量值中第一个遇到的指定字符串

语法：echo ${var/str}

Shell
#下例表示删除变量值中第一个遇到的"@" # teststr="zsy@think@linux" # echo ${teststr/@} zsythink@linux

1 2 3 4 | #下例表示删除变量值中第一个遇到的"@" # teststr="zsy@think@linux" # echo ${teststr/@} zsythink@linux

删除变量值中所有的指定字符串

语法：echo ${var//str}

Shell
#下例表示删除字符串中所有的"@" # teststr="zsy@think@linux" # echo ${teststr//@} zsythinklinux

1 2 3 4 | #下例表示删除字符串中所有的"@" # teststr="zsy@think@linux" # echo ${teststr//@} zsythinklinux

特殊情况

Shell
刚才总结了两种语法 语法一：删除变量值中所有的指定字符串的语法为echo ${var//str} 语法二：删除变量值中第一个遇到的指定字符串的语法为echo ${var/str} 如果，我们要删除字符串"/usr/local/chroot/usr/local"中第一个遇到的"/usr"，该怎么办呢？ 正常情况下，我们会套用上述语法二，将语法二中的"str"更改为"/usr"，套用语法二后的命令如下 # teststr="/usr/local/chroot/usr/local/nginx" # echo ${teststr//usr} 但是，套用语法二后的命令正好与上述语法一的语法结构相同，所以，本意是删除字符串中第一个遇到的"/usr"，但是最终结果却变为删除字符串中所有的"usr"，执行结果如下 # teststr="/usr/local/chroot/usr/local/nginx" # echo ${teststr//usr} //local/chroot//local/nginx 聪明如你一定想到了，这种情况需要对"/"进行转义，示例如下 # teststr="/usr/local/chroot/usr/local/nginx" # echo ${teststr/\/usr} /local/chroot/usr/local/nginx

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 刚才总结了两种语法 语法一：删除变量值中所有的指定字符串的语法为echo ${var//str} 语法二：删除变量值中第一个遇到的指定字符串的语法为echo ${var/str} 如果，我们要删除字符串"/usr/local/chroot/usr/local"中第一个遇到的"/usr"，该怎么办呢？ 正常情况下，我们会套用上述语法二，将语法二中的"str"更改为"/usr"，套用语法二后的命令如下 # teststr="/usr/local/chroot/usr/local/nginx" # echo ${teststr//usr} 但是，套用语法二后的命令正好与上述语法一的语法结构相同，所以，本意是删除字符串中第一个遇到的"/usr"，但是最终结果却变为删除字符串中所有的"usr"，执行结果如下 # teststr="/usr/local/chroot/usr/local/nginx" # echo ${teststr//usr} //local/chroot//local/nginx 聪明如你一定想到了，这种情况需要对"/"进行转义，示例如下 # teststr="/usr/local/chroot/usr/local/nginx" # echo ${teststr/\/usr} /local/chroot/usr/local/nginx

删除变量值中位于行首的指定字符串

语法：echo ${var/#str}

Shell
#下例表示删除字符串中行首的"H" # teststr="H.H.H.H.H.H" # echo ${teststr/#H} .H.H.H.H.H #下例表示删除字符串中行首的"#" # teststr="#zsy#think#linux" # echo ${teststr/##} zsy#think#linux

1 2 3 4 5 6 7 8 9 | #下例表示删除字符串中行首的"H" # teststr="H.H.H.H.H.H" # echo ${teststr/#H} .H.H.H.H.H #下例表示删除字符串中行首的"#" # teststr="#zsy#think#linux" # echo ${teststr/##} zsy#think#linux

特殊情况

Shell
参考之前的特殊情况，即可发现，由于删除字符串中行首的字符时需要使用语法"/#"，所以如果想要删除字符串中第一个遇到的"#"时，则不能使用"/#"，需要对"#"进行转义，示例如下，删除字符串中第一个遇到的"#" # teststr="zsy#think#linux" # echo ${teststr/\#} zsythink#linux

1 2 3 4 | 参考之前的特殊情况，即可发现，由于删除字符串中行首的字符时需要使用语法"/#"，所以如果想要删除字符串中第一个遇到的"#"时，则不能使用"/#"，需要对"#"进行转义，示例如下，删除字符串中第一个遇到的"#" # teststr="zsy#think#linux" # echo ${teststr/\#} zsythink#linux

删除变量值中位于行尾的指定字符串

语法：echo ${var/%str}

Shell
#下例表示删除字符串中行尾的"H" # teststr="H.H.H.H.H.H" # echo ${teststr/%H} H.H.H.H.H. #下例表示删除字符串中行尾的"%" # teststr="zsy%think%linux%" # echo ${teststr/%%} zsy%think%linux

1 2 3 4 5 6 7 8 9 | #下例表示删除字符串中行尾的"H" # teststr="H.H.H.H.H.H" # echo ${teststr/%H} H.H.H.H.H. #下例表示删除字符串中行尾的"%" # teststr="zsy%think%linux%" # echo ${teststr/%%} zsy%think%linux

特殊情况

Shell
参考之前的特殊情况，即可发现，由于删除字符串中行尾的字符时需要使用语法"/%"，所以如果想要删除字符串中第一个遇到的"%"时，则不能使用"/%"，需要对"%"进行转义 #示例如下，删除字符串中第一个遇到的"%" # teststr="zsy%think%linux%" # echo ${teststr/\%} zsythink%linux%

1 2 3 4 5 | 参考之前的特殊情况，即可发现，由于删除字符串中行尾的字符时需要使用语法"/%"，所以如果想要删除字符串中第一个遇到的"%"时，则不能使用"/%"，需要对"%"进行转义 #示例如下，删除字符串中第一个遇到的"%" # teststr="zsy%think%linux%" # echo ${teststr/\%} zsythink%linux%

### 替换字符串的操作

将变量值中第一个遇到的str1替换成str2

语法：echo ${var/str1/str2}

Shell
#下例表示将字符串中第一个遇到的"w"替换成"abc" # teststr="www" # echo ${teststr/w/abc} abcww

1 2 3 4 | #下例表示将字符串中第一个遇到的"w"替换成"abc" # teststr="www" # echo ${teststr/w/abc} abcww

将变量值中所有的str1替换成str2

语法：echo ${var//str1/str2}

Shell
#下例表示将字符串中所有"w"替换成"abc" # teststr="www" # echo ${teststr//w/abc} abcabcabc

1 2 3 4 | #下例表示将字符串中所有"w"替换成"abc" # teststr="www" # echo ${teststr//w/abc} abcabcabc

特殊情况

Shell
某些情况下需要进行转义，参考"删除字符串操作"总结部分的特殊情况。

1 | 某些情况下需要进行转义，参考"删除字符串操作"总结部分的特殊情况。

将变量值中位于行首的str1替换成str2

语法：echo ${var/#str1/str2}

Shell
#下例表示将字符串中位于行首的abc替换成123 # teststr="abcdefabc666abc888abc" # echo ${teststr/#abc/123} 123defabc666abc888abc

1 2 3 4 | #下例表示将字符串中位于行首的abc替换成123 # teststr="abcdefabc666abc888abc" # echo ${teststr/#abc/123} 123defabc666abc888abc

特殊情况

Shell
某些情况下需要对#号进行转义，参考"删除字符串操作"总结部分的特殊情况。

1 | 某些情况下需要对#号进行转义，参考"删除字符串操作"总结部分的特殊情况。

将变量值中位于行尾的str1替换成str2

语法：echo ${var/%str1/str2}

Shell
#下例表示将字符串中位于行尾的abc替换成666 # teststr="abcdefabc666abc888abc" # echo ${teststr/%abc/666} abcdefabc666abc888666

1 2 3 4 | #下例表示将字符串中位于行尾的abc替换成666 # teststr="abcdefabc666abc888abc" # echo ${teststr/%abc/666} abcdefabc666abc888666

特殊情况

Shell
某些情况下需要对%号进行转义，参考"删除字符串操作"总结部分的特殊情况。

1 | 某些情况下需要对%号进行转义，参考"删除字符串操作"总结部分的特殊情况。

好了，关于变量操作、字符串操作就总结到这里，希望这篇文章能够对你有所帮助。

我的微信公众号
关注"实用运维笔记"微信公众号，当博客中有新文章时，可第一时间得知哦~
赞 19
赏
分享

- Shell（bash）

- 版权声明：本站原创文章，于2017年9月10日17:58:45，由 朱双印 发表，共 4060 字。
- 如需转载，请在文章头部注明出处：shell中常用的变量处理、字符串操作（之三） | 朱双印博客

shell中常用的变量处理、字符串操作（之二）
shell中常用的变量处理、字符串操作（之一）
bash中 [ ] 与 [[ ]] 的区别
shell中’-gt’与’>’的区别

### 发表评论取消回复

欢迎 pangzi 再次光临！
修改信息

正在提交, 请稍候...
#

昵称*

邮箱*

网址

有回复时邮件通知我

## 目前评论：7 其中：访客 6 博主 1

2. ray 0
   回复 2020年5月30日 下午5:00 沙发

   真正的深入浅出。

4. panf_mua 0
   回复 2019年11月26日 上午11:27 板凳

   [root@ali_mua shell]# cat test.sh
   #!/bin/bash
   workdir=
   ${workdir:-“ttt”}
   echo $workdir
   [root@ali_mua shell]# bash -x test.sh
   + workdir=
   + ttt
   test.sh: line 3: ttt: command not found
   + echo

   [root@ali_mua shell]# cat test.sh
   #!/bin/bash
   workdir=
   ${workdir:-“ls”}
   echo $workdir
   [root@ali_mua shell]# bash -x test.sh
   + workdir=
   + ls
   pgsql test.sh
   + echo

   大佬 ， ${workdir:-“ttt”} 这个（ttt）貌似只能使用 系统命令，用任意字符串的话 脚本执行会提示command not found 替换成ls后就打印了当前目录下的文件
   并且 最后 输出 的变量 是 空
   不知道是不是内核、系统版本的问题 内核 是 4.19.57-15.1.al7.x86_64 系统是阿里的镜像Aliyun Linux release 2.1903 (Hunting Beagle)

6. nc -l 520 1
   回复 2019年3月22日 下午9:36 地板

   总结的特好，但是都说运维是吃青春饭，你怎么看

   - 木木 0
     回复 2019年4月4日 下午8:37 1层

     @nc -l 520 ….互联网那个不是，，

8. tex 1
   回复 2018年5月28日 上午9:56 4楼

   博主的变量处理真的实用,不管是我自己在学习的shell脚本还是用别人脚本出错都能看的懂了。

10. 早 3
    回复 2017年10月8日 下午4:43 5楼

    朱兄，在掌握了LINUX基础后真的不知有什么工作可以找？

    - 朱双印 Admin
      回复 2017年10月9日 上午10:06 1层

      @早 ……顺其自然吧兄弟，找一个基础运维的工作，入门就好了，加油~~

- 文章目录

×
×
拖拽到此处
图片将完成下载