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

- 8

- A+

所属分类：Shell 编程

在shell中，当我们已经获取到某个变量的变量值的时候，可能还需要对变量值进行一定的处理，才能到我们最终想要的结果，今天我们就来聊聊shell中常见的变量处理方法，我们通常会对变量进行如下处理。

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

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

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

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

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

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

上述处理都是一些常见的操作，我们一个一个慢慢聊，这篇文章中，我们只对前两种操作进行总结，即怎样获取变量长度，以及怎样对变量值进行截取。

## 一、获取变量长度

通常，我们有可能需要获取变量值的长度，比如，变量中存放了一个字符串，我们需要获取字符串的长度，则可以使用如下方法。

如上图所示，website变量的值为"www.zsythink.net"，"www.zsythink.net"字符串一共由16个字符组成，当输出${#website}时，即可输出变量website的长度，很简单吧。

## 二、截取变量

有时候，我们只是需要变量值中的某一段，所以，我们需要截取这段内容为我们所用。而截取变量的方法又有不少，我们一一道来。

### 从指定位置开始截取字符串

通常，我们需要从指定的位置开始截取字符串，截取到字符串的末尾，示例如下。

上例中的":4"表示从website变量值的第4个字符开始，截取到变量值的末尾。

细心如你一定发现了，上例中，所谓的从第4个字符开始截取，是"从左向右"数的第4个字符，换句话说，就是从正数第4个字符开始截取，截取到字符串的末尾，如果我们想要从倒数第4个字符开始截取，截取到字符串的末尾，我们该怎么办呢？示例如下

上例中的":0-4"表示从website变量值的倒数第4个字符开始，截取到变量值的末尾。

从上例可以看出，":0-4"中的"0"可以使用"空格"代替，效果是相同的，但是，从上例中可以看出，"冒号"与"负号"之间如果不存在任何字符，则无法起到截取字符的效果，所以，上图中第三种写法是错误的。

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

除了能够指定截取操作的开始位置，我们还能够指定截取的长度，比如，从变量的第4个字符开始截取，截取8个字符的长度，示例如下。

没错，":4:8"表示从正数第4个字符开始截取，向后截取8个字符的长度。

聪明如你一定想到了，我们能不能从倒数的位置开始，截取指定长度的字符呢？必须能的，示例如下。

如上图所示，":0-12:9"表示从倒数第12个字符开始，向后截取9个字符，与之前的示例同理，"冒号"与"负号"之间如果不存在任何字符，则无法起到截取字符的效果，所以，上图中第三种写法是错误的。

在上述示例中，我们指定了截取字符的长度，比如上例中的":0-12:9"，表示截取9个字符的长度，其实，在centos7中，我们可以将截取字符的长度指定为"负数"，但是注意，centos6中截取字符串的长度不能为"负数"，否则会报错，我们来看看在centos7中，将截取长度指定为"负数"后的效果。示例如下

如上图所示，在centos7中,":0-12"表示从倒数第12个字符开始，向后截取所有字符，当同时指定截取长度为":-4"时，表示从倒数第12个字符向后截取所有字符以后，删除截取以后的字符的最后4个字符，换句话说，也可以理解成截取最后12个字符的前8个字符。

但是，使用上述方法是需要注意一点，删除截取以后的字符数量不能大于现有字符的数量，示例如下。

如上图所示，我们一共就截取了12个字符，如果将截取长度指定为"-13"，则会报上述错误：-bash: XX : substring expression < 0

注意：在centos7中，使用这种写法的时候要计算好截取的范围，否则会报错

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

所谓的"掐头去尾"，其实就是删除某个字符左侧的所有字符（掐头），或者删除某个字符右侧的所有字符（去尾），这样说可能不容易理解，我们来看一些小例子，就能明白了。

先从所谓的"掐头"聊起，示例如下。

如上例所示，我们使用"#*."即可删除字符串中从左向右数第一个 "." 以及其左侧的全部字符，这就是所谓"掐头去尾"中的掐头，准确的说，应该是掐去头部，截取尾部。

聪明如你一定已经会举一反三了，我们可以把上例中的 "." 替换成其他字符，也是同样适用的，示例如下。

如上图所示，"#*A"表示删除字符串中从左向右第一个遇到的A，以及其左侧的字符。

换句话说，从左向右第一个遇到的A以及其左侧的字符都被当做"头部"掐去了。

其实，除了能够使用"#*字符"的语法进行"掐头"，其实还有另一种方法，也能实现"掐头"的操作，只不过它们略有些不同，示例如下。

如上例所示，"##*."表示删除字符串中从左向右最后一个遇到的 "." ，以及其左侧的字符。

换句话说，从左向右最后一个遇到的 "." 以及其左侧的字符都被当做"头部"掐去了。

没错，通过上例即可对比出两种写法的不同。

"#*."表示删除字符串中从左向右第一个遇到的 "." ，以及其左侧的字符。

"##*."表示删除字符串中从左向右最后一个遇到的 "." ，以及其左侧的字符。

当然，上例中的"."也是可以根据实际情况替换成其他字符的，示例如下。

经过上述示例，你应该已经明白了，赶紧动手试试吧。

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

与之前描述的"掐头截取"相似，只要理解了之前的示例，再来理解"去尾截取"，简直不要太简单。

我们先来看一个小示例。

如上图所示，"%/*"表示删除字符串中从右向左第一个遇到的 "/" ，以及其右侧的字符。

换句话说，从右向左第一个遇到的 "/" 以及其右侧的字符都被当做"尾部"去掉了。

举一反三，我们可以根据实际情况，将上例中的"/"替换成别的字符，示例如下。

聪明如你，一定想到了，"去尾"截取法不止有上述一种方法，还有另一种"去尾"截取法，它们之间也略有不同，示例如下

上例中，"%%/*"表示删除字符串中从右向左最后一个遇到的 "/" ，以及其右侧的字符。

换句话说，从右向左最后一个遇到的 "/" 以及其右侧的字符都被当做"尾部"去掉了。

## 小结

我们对文章中的语法进行一次总结，方便以后回顾。

### 获取字符串长度

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

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

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

#下例表示从正数第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

这篇文章就总结到这里，字符串的其他操作，我们会另总结为一篇文章。

希望这篇文章能够帮到你，常来呦~~亲~~~

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

- Shell（bash）

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

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

### 发表评论取消回复

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

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

昵称*

邮箱*

网址

有回复时邮件通知我

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

2. tzwsoho 0
   回复 2019年12月11日 上午10:34 沙发

   如果既要截头又要截尾，是不是只能用个临时变量了？我测试这样的方式是不行的
   var=”www.zsythink.net”
   echo ${var#*.%.*}
   输出还是www.zsythink.net

4. 灰太狼 1
   回复 2019年6月15日 下午7:41 板凳

   cut 和 expr 命令也可以截取

6. Jerry 0
   回复 2018年4月17日 上午10:43 地板

   博主，通过你的文章来学习，我做了一个截取的尝试，
   test=“192.168.1.1空格192.168.1.2”
   echo ${test#*\s}
   可是没有起到效果，请博主赐教一下。

   - LMJ 0
     回复 2019年1月25日 上午11:02 1层

     @Jerry 你可以把 \s 改成 ‘ ‘

8. 我的电脑 3
   回复 2017年10月20日 下午9:28 4楼

   博主知道编译安装和免编译安装有什么区别吗？网上我查了也没看到有什么资料，今天我安装mysql时候编译安装和免编译安装的方式，我简单的看了下大有不同，但是这免编译安装以前都没听过

   - 采蘑菇的小男孩 0
     回复 2017年12月4日 下午3:32 1层

     @我的电脑 编译安装可以移植方便升级，免编译安装就有些无语。。。。你可以在linux社区看看

10. 问天 1
    回复 2017年8月31日 下午2:01 5楼

    棒棒的！赞一下..

    - 朱双印 Admin
      回复 2017年8月31日 下午2:47 1层

      @问天 好久不见，加油~

- 文章目录

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