Bash技巧:使用参数扩展获取变量的子字符串和字符串长度

在 bash 中,通常使用 ${parameter} 表达式来获取 parameter 变量的值,这是一种参数扩展 (parameter expansion)。
Bash 还提供了其他形式的参数扩展,可以对变量值做一些处理,起到操作字符串的效果。例如:

  • ${parameter:offset:length}parameter 变量值的第 offset 个字符开始,获取 length 个字符,得到子字符串。
  • ${#parameter} 获取 parameter 变量值的字符串长度。

注意:这些表达式都不会修改 parameter 自身的变量值,它们只是基于 parameter 变量值扩展得到新的值。
如果要保存这些值,需要赋值给具体的变量。

查看 man bash 的 Parameter Expansion 小节,就能看到相关说明。具体举例说明如下。

${parameter:offset}${parameter:offset:length}

查看 man bash 对 ${parameter:offset}${parameter:offset:length} 的说明如下:

Substring Expansion.
Expands to up to length characters of the value of parameter starting at the character specified by offset.
If parameter is @, an indexed array subscripted by @ or *, or an associative array name, the results differ as described below.

If length is omitted, expands to the substring of the value of parameter starting at the character specified by offset and extending to the end of the value. length and offset are arithmetic expressions.

If offset evaluates to a number less than zero, the value is used as an offset in characters from the end of the value of parameter.

If length evaluates to a number less than zero, it is interpreted as an offset in characters from the end of the value of parameter rather than a number of characters, and the expansion is the characters between offset and that result.

Note that a negative offset must be separated from the colon by at least one space to avoid being confused with the :- expansion.

即,${parameter:offset:length} 表达式从 parameter 变量值的第 offset 个字符开始,一直获取 length 个字符,得到一个子字符串,会包括第 offset 个字符自身。

${parameter:offset} 表达式省略了 length 参数,会从 parameter 变量值的第 offset 个字符开始一直获取到末尾。

这里的 lengthoffset 可以是算术表达式。
字符串的 offset 从 0 开始。

如果 offset 的数值小于 0,那么这个值被用作 parameter 变量值的末尾偏移,从后往前获取字符。
如果 length 数值小于 0,它会被当成 parameter 变量值的末尾偏移,而不是当作总的字符数目,且扩展后的结果是在这两个偏移之间的字符。

注意:一个负数的偏移量必须用至少一个空格和冒号分割开,以避免和 :- 扩展产生混淆。
即,这种情况下的冒号 : 和 负号 - 之间至少要有一个空格,类似于 : - 的形式。

具体举例说明如下:

$ value="This is a test string."
$ echo ${value:5}
is a test string.
$ echo ${value:5:2}
is
$ echo ${value:5: -4}
is a test str
$ echo ${value: -7:3}
str
$ echo ${value: -7: -1}
string

可以看到,${value:5} 获取从 value 变量值的第 5 个字符开始,一直到末尾的全部字符。
注意偏移量是从 0 开始,获取到的子字符串包括第 5 个字符自身。

${value:5:2}value 变量值的第 5 个字符开始,获取包括该字符在内的两个字符,也就是 "is" 字符串。

当所给的 length 参数值为负数时,负号和冒号之间要用空格隔开。
此时 length 参数不表示要获取的字符个数,而是表示对应 parameter 变量值从后往前的偏移,而且这个偏移是从 1 开始。
${value:5: -4} 表示从 value 变量值的第 5 个字符开始,一直获取到倒数第 4 个字符为止,不包括倒数第 4 个字符。

当所给的 offset 参数值为负数时,负号和冒号之间要用空格隔开。
此时 offset 参数对应 parameter 变量值从后往前的偏移,而且这个偏移是从 1 开始。
${value: -7:3} 表示从 value 变量值的倒数第 7 个字符串开始,获取包括该字符在内的三个字符,也就是 "str" 字符串。

${value: -7: -1} 表示从 value 变量值的倒数第 7 个字符串开始,一直获取到倒数第 1 个字符为止。
包括倒数第 7 个字符,不包括倒数第 1 个字符。
具体得到的是 "string" 字符串,不包含最后的点号 .

${#parameter}

查看 man bash 对 ${#parameter} 的说明如下:

Parameter length. The length in characters of the value of parameter is substituted.
If parameter is * or @, the value substituted is the number of positional parameters.
If parameter is an array name subscripted by * or @, the value substituted is the number of elements in the array.

即,如果 parameter 变量值是字符串,则 ${#parameter} 可以获取到对应字符串的长度。

具体举例说明如下:

$ value="123456"
$ echo ${#value}
6

注意:在 bash 的参数扩展中,数字属于位置参数(positional parameters),可以用数字来引用传入脚本或者函数的参数。
当用在当前表达式时,就表示获取所传参数的字符串长度。
例如 $1 对应传入的第一个参数,那么 ${#1} 对应所传入第一个参数的字符串长度。
具体举例如下:

$ function param_length() { echo ${#1}; }
$ param_length 123456
6

可以看到,param_length 函数使用 ${#1} 获取到所给第一个参数值的长度。

Image placeholder
jason2014
未设置
  74人点赞

没有讨论,发表一下自己的看法吧

推荐文章
Bash技巧:详解用$获取变量值是否要加双引号或者大括号

本篇文章介绍在Linuxbashshell中,用$获取变量值时,是否要加双引号、是否要加大括号。用$获取变量值是否要加双引号在bashshell脚本中,用$来获取变量值时,有一些不加双引号,例如$ar

Go语言高级编程_1.3 数组、字符串和切片

1.3数组、字符串和切片 在主流的编程语言中数组及其相关的数据结构是使用得最为频繁的,只有在它(们)不能满足时才会考虑链表、hash表(hash表可以看作是数组和链表的混合体)和更复杂的自定义数据结构

Ubuntu常用技巧:npm下载很慢的超简单解决方法

在使用npm下载时,速度特别特别慢,等了半小时还是纹丝不动:尝试了一些方法,效果不是很明显,最终发现一种简单有效的方法:1.终端输入命令,显示当前的镜像地址:npmgetregistry2.再输入命令

Stack Overflow 上 370万浏览量的一个问题:如何比较 Java 的字符串?

在逛StackOverflow的时候,发现了一些访问量像喜马拉雅山一样高的问题,比如说这个:如何比较Java的字符串?访问量足足有370万+,这不得了啊!说明有很多很多的程序员被这个问题困扰过。PS:

分享 6 个 Go 处理字符串的技巧

如果你从Ruby或者Python转型到Go,将会有很多语言差异需要学习,其中很多问题都是围绕处理string类型。下面是一些字符串的技巧,这些技巧解决了我在使用Golang的最初几周中遇到的问题。

《Go语言程序设计》读书笔记(六) 基于共享变量的并发

竞争条件 在一个线性(就是说只有一个goroutine的)的程序中,程序的执行顺序只由程序的逻辑来决定。在有两个或更多goroutine的程序中,每一个goroutine内的语句也是按照既定的顺序去执

ES6系列之变量的解构赋值

1.什么是解构?ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。它在语法上比ES5所提供的更加简洁、紧凑、清晰。它不仅能减少你的代码量,还能从根本上改变你的编码方式。2.数

重新认识一下JS声明变量的六种方式吧

开始先说一下JS中有哪六种变量的声明方法吧,然后我们带着三个问号去看文章:what?how?where?六种声明变量的方法: var let const function import class 没

jquery如何判断字符串是否包含指定字符?

方法一:使用indexOf()和lastIndexOf()方法案例:varCts="bblText"; if(Cts.indexOf("Text")>=0){ alert('Cts中包含Text字符串

笨办法学 Linux Bash:Shell、`.profile`、`.bashrc`、`.bash_history`

Bash:Shell、.profile、.bashrc、.bash_history。 当使用CLI(命令行界面)来使用Linux时,你正在与一个名为shell的程序进行交互。所有你输入的都传递给she

Nginx 配置常用参数,看这一篇就够了

最近在全面学习Nginx,当作笔记了,如有错误,欢迎指出或深入交流。 主模块 #配置用户或者组,默认为nobodynobody。 #userwwwwww; #Nginx开启的worker进程数,

Nginx 配置常用参数,看这一篇就够了

主模块 #配置用户或者组,默认为nobodynobody。 #userwwwwww; #Nginx开启的worker进程数,建议为CPU的核数 #worker_processes2; #指定ngi

万万没想到,HashMap默认容量的选择,竟然背后有这么多思考!?

集合是Java开发日常开发中经常会使用到的,而作为一种典型的K-V结构的数据结构,HashMap对于Java开发者一定不陌生。在日常开发中,我们经常会像如下方式以下创建一个HashMap:Map ma

如何在 Go 中使用切片容量和长度

来做一个快速测验-以下代码输出什么?vals:=make([]int,5) fori:=0;i

第 10 节:复合类型-5. 指针 -- 指针与指针变量 7. 结构体指针变量

7.结构体指针变量我们前面定义了指针指向了数组,解决了数组引用传递的问题。那么指针是否可以指向结构体,也能够解决结构体引用传递的问题呢?完全可以。\ 下面我们先来看一下,结构体指针变量的定义:\\ 也

实操讲解:使用Keras中的自动编码器进行极端罕见事件分类

在这篇文章中,我们将学习如何实现用自动编码器来构建稀有事件分类器。我们将使用来自此处的真实稀有事件数据集。背景什么是极端罕见的事件?在一个罕见的问题中,我们有一个不平衡的数据集。意思是,我们得到的阳性

GoWeb教程_07.6. 字符串处理

字符串在我们平常的Web开发中经常用到,包括用户的输入,数据库读取的数据等,我们经常需要对字符串进行分割、连接、转换等操作,本小节将通过Go标准库中的strings和strconv两个包中的函数来讲解

Java 8 API 示例:字符串、数值、算术和文件

Java8API示例:字符串、数值、算术和文件 大量的教程和文章都涉及到Java8中最重要的改变,例如lambda表达式和函数式数据流。但是此外许多现存的类在JDK8API中也有所改进,带有一些实用的

算法题:判断括号字符串是否有效

题目来源于力扣 理论基础 堆栈&队列 判断括号字符串是否有效 题目描述 给定一个只包括'(',')','{','}','[',']'的字符串,判断字符串是否有效。 有效字符串需满足:左括号必

算法题:判断括号字符串是否有效

题目来源于力扣 理论基础 堆栈&队列 判断括号字符串是否有效 题目描述 给定一个只包括'(',')','{','}','[',']'的字符串,判断字符串是否有效。 有效字符串需满足:左括号必

PHP 开发工程师基础篇 - PHP 字符串

PHP开发工程师基础篇-PHP字符串字符串(String)字符串是一系列字符的集合.如"abc".在PHP中,一个字符代表一个字节,一个字节(Byte)有8比特(bit).PHP仅支持256字符集,因

字符串类型

String的声明:变量值需要用引号(单、双、三引号)包装起来。声明方式的选择:如果字符串中有双引号,推荐使用单引号声明(HTML代码)。如果字符串中有单引号,推荐使用双引号声明(PHP,python

字符串

字符串加号‘+’做字符连接运算(只能同类运算) 字符串赋值运算乘号‘*’做字符串重复累计运算。复制的次数必须是整形而不能是浮点类型。 字符串索引操作,只需要将字符串当作列表操作,填入下标即可,也可做列

redis数据结构(二) - 字符串

基于redis5.0的版本。字符串编码:字符串对象的编码可以是int,raw或者embstr。1.rawraw就是redisObject+sds,即redisObject的ptr指针指向一个sds对象

java字符串“我是谁”的转码问题

微信公众号:爱问CTO专业编程问答社区www.askcto.com 问题出场publicstaticvoidmain(String[]args)throwsException{ Stringa="我是