本文主要对Shell中的字符串进行简单总结,另外本文所使用的Linux环境为CentOS Linux release 8.1.1911,所使用的Shell为bash 4.4.19(1)-release

一、引用机制

字符串是Shell编程中最常用的数据类型。字符串可以用单引号或双引号引起来,也可以不用引号,还可以使用$加一对单引号引起来,这几种方式也可以自由组合。示例如下:

引用(Quoting)用来去除Shell中某些字符或单词的特殊含义。它可以用来禁止对特殊字符的特殊处理,防止保留字被识别为特殊字符,并防止参数扩展。每个Shell元字符对Shell都有特殊的含义,必须引起来才能代表它自己。如果使用了命令历史扩展的功能,则历史扩展字符(通常是!)也引用起来以取消历史扩展。

注意:这里所说的引用(quote)是指字符串周围的引号,而不是C++或Java中对对象地址的引用(reference)。

有三种引用机制:转义字符、单引号和双引号。

上面出现的一些术语解释:

  • 元字符(metacharacter):当不加引号时能分隔单词的字符。包括空格、制表符、换行符或以下字符之一:|&;()<>
  • 单词(word):被Shell视为一个单元的字符序列,它不能包含未加引号的元字符。
  • 保留字(reserved word):对Shell有特殊意义的单词,它们大部分是用来构建Shell的控制结构的,如forwhile
  • 参数(parameter):参数是存储值的实体。它可以是一个名字,一个数字,或者#*@等特殊字符之一。
  • 参数扩展(parameter expansion):参数前面加$,要扩展的参数(变量)名和符号可以放到大括号{}中,大括号可选,但可用于保护要扩展的变量不受紧跟在它后面的字符的影响,否则这些字符会被解释成名称的一部分。

1.无引号

不使用引用机制时,就不能去除Shell中某些字符或单词的特殊含义,所有的特殊字符都会进行特殊处理。不使用引用机制并带有部分特殊字符的示例如下:

如上图所示,这些特殊字符会进行特殊处理。直接使用echo输出时可以有空格:

2.转义字符

没有转义的反斜杠\是转义字符,它能保留其下一个字符的字面值,除非这个字符是换行符。如果出现\newline\是某行最后一个字符),并且反斜杠本身没有被引用,\newline将被视为行连续符,也就是说,它将从输入流中删除并有效地忽略。

上面不使用引用机制并带有部分特殊字符的示例中的特殊字符都会被处理,使用转义字符进行转义可以保留它们的字面值,这些特殊字符也就不会进行特殊处理,保持原样输出,一部分特殊字符前面加上转义字符的示例如下:

#!/bin/bashstr1=hello\ world
str2=hello\|world
str3=hello\&world
str4=hello\;world
str5=hello\(world
str6=hello\)world
str7=hello\<world
str8=hello\>world
str9=hello\$world
str10=hello\\world
str11=hello\!world
str12=hello\`pwd\`
str13=hello\'world
str14=hello\"worldecho "str1:${str1}"
echo "str2:${str2}"
echo "str3:${str3}"
echo "str4:${str4}"
echo "str5:${str5}"
echo "str6:${str6}"
echo "str7:${str7}"
echo "str8:${str8}"
echo "str9:${str9}"
echo "str10:${str10}"
echo "str11:${str11}"
echo "str12:${str12}"
echo "str13:${str13}"
echo "str14:${str14}"

执行结果:

转义字符\后面是换行符并且反斜杠本身没有被引用,一个示例如下:

如上图所示,换行符被视为行连续符,\和换行符都被忽略。

3.单引号

将字符括在单引号'中可以保留引号内每个字符的字面值。单引号之间不能再出现单引号,即使它前面有反斜杠。

一些使用单引号的示例如下::

#!/bin/bashstr1='hello world'
str2='hello|world'
str3='hello&world'
str4='hello;world'
str5='hello(world'
str6='hello)world'
str7='hello<world'
str8='hello>world'
str9='hello$world'
str10='hello\world'
str11='hello!world'
str12='hello`pwd`'
str13='hello"world'
str14='hello\$world'
str15='hello\\world'
str16='hello\`pwd\`'
str17='hello\"world'
str18='hello\!world'
str19='hello\&world'
str20='hello"${str1}"world'echo "str1:${str1}"
echo "str2:${str2}"
echo "str3:${str3}"
echo "str4:${str4}"
echo "str5:${str5}"
echo "str6:${str6}"
echo "str7:${str7}"
echo "str8:${str8}"
echo "str9:${str9}"
echo "str10:${str10}"
echo "str11:${str11}"
echo "str12:${str12}"
echo "str13:${str13}"
echo "str14:${str14}"
echo "str15:${str15}"
echo "str16:${str16}"
echo "str17:${str17}"
echo "str18:${str18}"
echo "str19:${str19}"
echo "str20:${str20}"

执行结果:

单引号之间不能出现单引号,使用转义也不行,示例如下:

最终输出的字符串中确实没有单引号。直接换行和反斜杠后跟换行符,示例如下:

4.双引号

将字符括在双引号"中可以保留引号内所有字符的字面值,除了$`\,以及在启用历史扩展时的!

  • 字符$`在双引号内保留其特殊含义。
  • 反斜杠仅在后跟$`"\或换行符之一时才具有特殊意义,在双引号中,反斜杠后跟这些字符之一,那么该反斜杠将被删除,反斜杠后面的字符没有特殊含义,那么反斜杠和该字符都会被保留,双引号中可以通过反斜杠跟一个双引号的形式出现另一个双引号。
  • 如果打开了历史扩展,!将导致历史扩展被执行,除非!用反斜杠进行了转义,并且!前面的反斜杠并不会被移除;当Shell处于POSIX模式时,!在双引号内没有特殊含义,即使启用了历史扩展。

一些使用双引号的示例如下:

#!/bin/bashstr1="hello world"
str2="hello|world"
str3="hello&world"
str4="hello;world"
str5="hello(world"
str6="hello)world"
str7="hello<world"
str8="hello>world"
str9="hello$world"
str10="hello\world"
str11="hello!world"
str12="hello`pwd`"
str13="hello'world"
str14="hello\$world"
str15="hello\\world"
str16="hello\`pwd\`"
str17="hello\"world"
str18="hello\'world"
str19="hello\!world"
str20="hello\&world"
str21="hello'${str1}'world"echo "str1:${str1}"
echo "str2:${str2}"
echo "str3:${str3}"
echo "str4:${str4}"
echo "str5:${str5}"
echo "str6:${str6}"
echo "str7:${str7}"
echo "str8:${str8}"
echo "str9:${str9}"
echo "str10:${str10}"
echo "str11:${str11}"
echo "str12:${str12}"
echo "str13:${str13}"
echo "str14:${str14}"
echo "str15:${str15}"
echo "str16:${str16}"
echo "str17:${str17}"
echo "str18:${str18}"
echo "str19:${str19}"
echo "str20:${str20}"
echo "str21:${str21}"

执行结果:

直接换行和反斜杠后跟换行符,示例如下:

单引号中反斜杠跟换行符最终仍然保持原样,而双引号中反斜杠跟换行符,该反斜杠被删除并且没有换行。命令行中使用!会进行历史扩展,双引号中有开启历史扩展的!的示例如下:

!-n是选择前n条命令。!前加了反斜杠转义后就不会执行历史扩展了,并且这里的反斜杠也没有被删除。

放在脚本中执行却不会进行历史扩展,脚本如下:

#!/bin/bashpwd
echo "!"
echo "!-2"
echo "\!-3"

执行结果:

5.ANSI-C引用

形式为$'string '的单词会被特殊处理。该词将会扩展为字符串,并按照ANSI C标准的规定替换反斜杠转义字符,扩展结果是单引号引用的,就好像$符号不存在一样。如果其中出现反斜杠转义序列,会按如下转义序列的含义替换:

转义字符 含义
\a 响铃
\b 退格删除
\e、\E 转义字符(不属于ANSI C)
\f 换页
\n 新行
\r 回车
\t 水平制表符
\v 垂直制表符
\\ 反斜杠
\’ 单引号
\" 双引号
\? 问号
\nnn 八位字符,其值为八进制值nnn(一到三个八进制数字)
\xHH 八位字符,其值为十六进制值HH(一个或两个十六进制数字)
\uHHHH Unicode(ISO/IEC 10646)字符,其值为十六进制值HHHH(一到四个十六进制数字)
\UHHHHHHHH Unicode(ISO/IEC 10646)字符,其值为十六进制值HHHHHHHH(一到八个十六进制数字)
\cx ctrl-x字符

一些使用ANSI C引用扩展字符串的示例如下:

#!/bin/bashstr1=$'hello$world'
str2=$'hello\world'
str3=$'hello!world'
str4=$'hello`pwd`'
str5=$'hello"world'
str6=$'hello\$world'
str7=$'hello\\world'
str8=$'hello\`pwd\`'
str9=$'hello\"world'
str10=$'hello\'world'
str11=$'hello\!world'
str12=$'hello\&world'
str13=$'hello"${str1}"world'
str14=$'hello\bworld'
str15=$'hello\eworld'
str16=$'hello\nworld'
str17=$'hello\rworld'
str18=$'hello\tworld'
str19=$'hello\vworld'
str20=$'hello?world'
str21=$'hello\?world'
str22=$'hello\101world'
str23=$'hello\x2Aworld'
str24=$'hello\u0023world'
str25=$'hello\U00005FC3world'echo "str1:${str1}"
echo "str2:${str2}"
echo "str3:${str3}"
echo "str4:${str4}"
echo "str5:${str5}"
echo "str6:${str6}"
echo "str7:${str7}"
echo "str8:${str8}"
echo "str9:${str9}"
echo "str10:${str10}"
echo "str11:${str11}"
echo "str12:${str12}"
echo "str13:${str13}"
echo "str14:${str14}"
echo "str15:${str15}"
echo "str16:${str16}"
echo "str17:${str17}"
echo "str18:${str18}"
echo "str19:${str19}"
echo "str20:${str20}"
echo "str21:${str21}"
echo "str22:${str22}"
echo "str23:${str23}"
echo "str24:${str24}"
echo "str25:${str25}"

执行结果:

6.Locale专用翻译

这个暂时用不到

在用双引号引起来的字符串前面加上美元符号$会导致该字符串根据当前语言环境进行翻译。如果当前语言环境为C或POSIX,或者没有可用的翻译,则忽略美元符号。如果字符串被翻译并替换了,替换的字符串将被双引号引起来。

二、字符串常见操作

1.获取字符串长度

方法:

# string为字符串变量名
${#string}

示例:

2.字符串的拼接

Shell拼接字符串不需要任何运算符,只需要把两个字符串并排放在一起就行。示例:

#!/bin/bashstr1="hello"
str2="world"
result1=${str1}${str2}
result2="${str1} ${str2}"
result3=${str1}','${str2}
result4=${str1}","${str2}
result5="${str1},${str2}"
result6="${str1}java,"hello"${str2}!"
result7="${str1}java"' hello'"${str2}"echo ${result1}
echo ${result2}
echo ${result3}
echo ${result4}
echo ${result5}
echo ${result6}
echo ${result7}

执行结果:

3.字符串的截取

方法:

# 从string字符串的左边第start个字符开始,向右截取到最后,start从0开始
${string:start}
# 从string字符串的左边第start个字符开始,向右截取length个字符
${string:start:length}
# 从string字符串的右边第start个字符开始,向右截取到最后,start从1开始
${string:0-start}
# 从string字符串的右边第start个字符开始,向右截取length个字符
${string:0-start:length}
# 从string字符串左边第一次出现*chars的位置开始,截取*chars右边的所有字符
${string#*chars}
# 从string字符串左边最后一次出现*chars的位置开始,截取*chars右边的所有字符
${string##*chars}
# 从string字符串右边第一次出现chars*的位置开始,截取chars*左边的所有字符
${string%chars*}
# 从string字符串右边最后一次出现chars*的位置开始,截取chars*左边的所有字符
${string%%*chars*}

示例:

#!/bin/bashurl="https://www.gnu.org/software/bash/manual/bash.html"
# 从左边第8个字符开始向右截取到最后
echo ${url:8}
# 从左边第29个字符开始向右截取4个字符
echo ${url:29:4}
# 从右边第42个字符开始向右截取到最后
echo ${url:0-42}
# 从右边第9个字符开始向右截取4个字符
echo ${url:0-9:4}
# 从左边第一次出现ba的位置开始截取右边的所有字符
echo ${url#*ba}
# 从左边最后一次出现sh的位置开始截取右边的所有字符
echo ${url##*sh}
# 从右边第一次出现ba的位置开始截取左边的所有字符
echo ${url%ba*}
# 从右边最后一次出现sh的位置开始截取左边的所有字符
echo ${url%%sh*}

执行结果:

Shell编程之字符串相关推荐

  1. 【linux】shell 编程之字符串与数组

    前言 对字符串的操作在众多的编程语言中可以说是最基础的了,字符串(String)就是一系列字符的组合.字符串是 Shell 编程中最常用的数据类型之一(除了数字和字符串,也没有其他类型了). 一.sh ...

  2. linux shell 文件空,linux shell编程 如何判断一个文件是否为空

    shell 判断文件/目录是否为空 jfkidear144932015-01-15 shell中如何判断一个变量是否为空 l_nan365492014-07-14 在shell中如何判断一个变量是否为 ...

  3. linux shell编程学习——数组使用

    linux的shell的编程方面很强大,最近在写脚本的时候,需要用到shell的数组.下面对最近的学习和使用做个简单的总结. 定义 linux的数组分两种,一种是普通的下标数组,一种是关联数组.前者和 ...

  4. shell编程之条件语句(文件测试,test命令,字符串和逻辑测试,if单支语句,if双支语句,if多支语句,case命令,用if写跑步小实验)

    文章目录 shell编程之条件语句 条件测试 test命令 整数值测试 free -m 提供了更简洁的查看系统内存使用情况: 字符串和逻辑测试 字符串 逻辑测试 一元运算符,二元运算符和三元运算符 i ...

  5. 自学shell编程——第1讲(基础概念、变量、符号、字符串处理)

    shell编程 1. 常见shell命令 ls cd more less pwd mkdir clear touch vim chmod grep cp ln mv man ps -ef 查看这些命令 ...

  6. shell编程范例之字符串操作[转]

    shell编程范例之字符串操作 下面是"在线新华字典"的解释: 字符串: 简称"串".有限字符的序列.数据元素为字符的线性表,是一种数据的逻辑结构.在计算机中可 ...

  7. 如让自己想学不好shell编程都困难?

    众所周知,shell是linux运维必备的技术,必须要掌握,但是shell语法复杂,灵活,网友掌握了语法也不知道如何应用到实际运维中,老男孩培训shell编程给所有linux运维人员带来了学好shel ...

  8. shell 不等于_关于shell编程中的整数值比较的两种方式的简单操作实例

    谈一谈关于shell编程中的整数值比较的两种方式 Shell编程有时处理一个对象时,需要我们对对象进行测试. 只有符合要求的才采取下一步操作,这样做的好处可以避免程序出错. 这个测试的对象可以是文件. ...

  9. Linux学习(十四)---大数据定制篇Shell编程

    文章目录 一.为什么要学习shell编程 二.Shell 是什么 三.shell 编程快速入门-Shell 脚本的执行方式 3.1 脚本格式要求 3.2 编写第一个 Shell 脚本 3.3 脚本的常 ...

最新文章

  1. 文章3:车载LIDAR点云数据中杆状地物自动提取与分类
  2. mysql查询解析过程_MySQL查询执行过程详解
  3. 倒序查10条数据_王者荣耀对抗路数据公布,尖端局吕布倒第一,夏洛特真的很意外...
  4. 如果输送知识不再重要,那么教育问题出在哪里?
  5. linux下打开大文件且搜索字符串的方法
  6. 使用docker的mysql镜像
  7. 希尔排序基础java代码_java 算法之希尔排序详解及实现代码
  8. 单调栈 leetcode整理(三)
  9. mysql客户端路由方式_20.3 在InnoDB 集群中 使用MySQL 路由
  10. phpunit autoload.php,关于php:Composer不会创建所有需要的phpunit包含路径
  11. 深入理解Tomcat系列之五:Context容器和Wrapper容器
  12. 火眼:利用FTA 服务器0day攻击全球百家企业的是 FIN11
  13. IFIX组态----安全与权限配置
  14. App性能优化:内存优化
  15. 补能的争议路线:快充会走向大一统吗?
  16. 浅谈自适应滤波器---(快速RLS算法)
  17. 关于KOT、KOL、KOC 理解
  18. 照片实现3D光影效果
  19. php 送货单管理系统,送货单管理软件下载
  20. 易车上汽车报价准不准

热门文章

  1. 数据表的清空有三种方式:
  2. java pjax_(转)PJAX的实现与应用
  3. 转载:歌词赏析《新鸳鸯蝴蝶梦》
  4. Struts2项目出现500错误
  5. 音量调节~01背包的到达问题
  6. OPPO第二颗自研芯片来了,首次实现192kHz/24bit无损音频蓝牙传输,台积电6nm工艺...
  7. php编程狼追兔子,C语言狼追兔子问题
  8. 2023前端面试题及答案整理(Vue)
  9. 公众号写作——经验分享
  10. 【JZOJ5407】Deep