字符串
在Bash中,变量是没有类型的,它们的值可以是任意字符串。因为变量值都是字符串,所以在Bash中进行的字符串操作都是对变量进行处理的。Bash中的字符串操作通过参数扩展来实现,也可以称为变量扩展,或者更具体地称为字符串参数扩展。 Bash中还存在其他形式的扩展详见扩展
一节
另外,Bash中确实没有字符串字面量的说法,而字符串字面量在脚本中用单引号或双引号表示,本质上也是一种字符串,也可以通过参数扩展进行操作。
通过变量
一节我们已经知道,变量使用${string}
其简写形式是$string
,字符串操作基本形式是${string}
,为了避免语法上冲突花括号{}
不能省略
基础
${#string} 获取字符串长度
url="https://www.jartap.com"
echo ${#url} # 输出 22
${string:-default}
如果string
变量已经存在并string
的值非空,则返回string
变量的值,否则返回default
,看下面的例子:
#!/bin/bash
# 设置一个非空字符串
string="Hello"
# 使用参数扩展来查看 string 的值
echo "${string:-default}" # 输出 "Hello",因为 string 已设置且非空
# 清除 string 变量
unset string
# 再次使用参数扩展来查看 string 的值
echo "${string:-default}" # 输出 "default",因为 string 未设置
# 使用另一个变量的值作为默认值
another_variable="World"
echo "${string:-$another_variable}" # 输出 "World",因为 string 未设置
${string:=variable_value}
如果string
变量已经存在并string
的值非空,则返回string
变量的值,否则返回default
,在返回default
之前,将default
给string
#!/bin/bash
string1=""
echo "Original: ${string1}" # 输出 "Original: "
echo "Expanded: ${string1:-default}" # 输出 "Expanded: default",但 string 的值仍然是空
echo "After: ${string1}" # 输出 "After: "
string2=""
echo "Original: ${string2}" # 输出 "Original: "
echo "Expanded: ${string2:=default}" # 输出 "Expanded: default",并且 string 的值被设置为 "default"
echo "After: ${string2}" # 输出 "After: default"
${string:+default}
如果 string
已设置并且非空,则扩展为 default
,如果 string 未设置或者为空,则不进行任何扩展(即结果为空字符串)
#!/bin/bash
# 设置一个非空字符串
string="Hello"
# 使用参数扩展来查看 string 的值(或 variable_value)
echo "${string:+World}" # 输出 "World",因为 string 已设置且非空
# 清除 string 变量
unset string
# 再次使用参数扩展来查看 string 的值(或 variable_value)
echo "${string:+World}" # 不输出任何内容,因为 string 未设置
# 使用另一个变量的值作为可能的扩展值
another_variable="Another World"
echo "${string:+$another_variable}" # 如果 string 已设置且非空,则输出 another_variable 的值;否则不输出
${string:?variable_value}
#!/bin/bash
string=""
# 如果 string 未设置或为空,则打印 "Error: string is not set" 并退出
echo "${string:?Error: string is not set}" # 输出错误消息并退出脚本
string="Hello"
# 现在 string 已设置且非空,所以输出其值
echo "${string:?Error: string is not set}" # 输出 "Hello"
前缀后缀
${parameter#word} 删除前缀
它用于从变量parameter
的值中删除匹配word
前缀。如果word
没有在parameter
的值中找到匹配项,那么 ${parameter#word}
就会返回 parameter
的原始值。
其中word
是模式匹配字符串(Pattern Matching), 关于模式匹配(Pattern Matching)详见这里
例如word可以是http*/
,在${parameter#word}
中采用最短匹配原则,匹配word
,请看示例:
#!/bin/bash
url="https://www.jartap.com/bash"
# 使用 # 删除前缀
prefix="https:*/"
no_prefix="${url#$prefix}"
echo "$no_prefix" # 输出:/www.jartap.com/bash,最短匹配原则导致结果以 /www 开头,而不是以www开通
${parameter##word}删除前缀
同${parameter#word}
一样的语法,只是采用最长匹配原则,匹配word
。
#!/bin/bash
url="https://www.jartap.com/bash"
# 使用 # 删除前缀
prefix="https:*/"
no_prefix="${url##$prefix}"
echo "$no_prefix" # 输出:bash,最长匹配原则
${parameter%word} 删除后缀
同${parameter#word}
一样的逻辑,采用最短匹配原则,匹配word
。只是这里删除的是后缀。
${parameter%%word}删除后缀
同${parameter##word}
一样的逻辑,采用最长匹配原则,匹配word
。只是这里删除的是后缀。
替换
${parameter/pattern/string}
${parameter//pattern/string}
${parameter/#pattern/string}
${parameter/%pattern/string}
转换
${parameter^pattern} ${parameter^^pattern} ${parameter,pattern} ${parameter,,pattern} ${parameter@operator}
子字符串
Bash中使用${string:position:length}
提前子字符串,注意在Bash中,字符串的索引从0开始,所以${string:0:5}
表示取字符串string
的前5个字符。
position
表示开始位置(包含这个位置的字符),可以为负数,表示从字符串末尾开始算起。为负数时候必须用()
括起来,否则返回完整字符串
length
表示子字符串的长度,可以为负数,表示子字符串结束位置(不包含此位置的字符),当length
时候计算出来的子字符串长度小于0时,则报错。为0时候返回空字符串。
position
和length
可以省略:省略position
表示从字符串开头开始算起,省略length
表示取到字符串末尾。
看些子字符串示例:
url="https://www.jartap.com"
echo ${url} 输出:https://www.jartap.com
echo ${url:0:5} #输出:https
echo ${url:8} #输出:www.jartap.com
echo ${url:8:3} #输出:www
echo ${url::5} #省略了position,position默认值为0,和${url:0:5}等价,输出:https
echo ${url:1:-1} #输出:ttps://ww.jartap.co
echo ${url::-4} #省略position,position默认为0,length为-4表示末尾第四个位置,输出:https://www.jartap
echo ${url:-4} #输出:position的位置没有使用()括起来,所以输出:https://www.jartap
echo ${url:(-4)} #输出:.com
echo ${url:(-4):2} #输出:.c
length=2
echo ${url:(-4):$length} #输出:.co
文件路径处理
https://blog.csdn.net/astrotycoon/article/details/50814031
模式匹配
注意:模式匹配并不是正则表达式,所以不要把模式匹配和正则表达式混淆。 模式匹配(Pattern Matching)可以理解为通配符,在Bash官方文档中没有关于通配符(wildcard)说法;取而代之的是在文件名扩展章节有Pattern Matching的说明。其展现出来的意思和通配符基本相同。
?????? 模式匹配在不同场景下具有不同的意义,已知的有:
- 文件名扩展场景
- 字符串扩展场景 ??????
在模式匹配中,除了特殊字符外,其他字符均代表自身,可以使用转义符号\
对特殊字符进行转义使其代表自身。比如\*
代表*
本身。除了使用使用\
进行转义之外也可以使用''
或者""
包裹让其代表自身,a'*'
、"a*"
、'a*'
、a"*"
都代表代表a*
本身。
touch a'*'.data ab.data
ls -l a'*'.data # 输出: a*.data,并没有ab.data
特殊字符有:
*
:代表任意个字符?
:代表一个字符[...]
:代表一个字符,其中[...]
中的字符代表任意一个字符,[!...]
表示任意一个非[...]
中的字符[[:class:]]
:代表一个字符,其中[:class:]
代表一个字符类别,[:alnum:]
代表字母和数字,[:alpha:]
代表字母,[:digit:]
代表数字,[:lower:]
代表小写字母,[:upper:]
代表大写字母,[:blank:]
代表空格和制表符,[:space:]
代表空格、制表符、换行符、回车符,- `[:punct:],
alnum alpha ascii blank cntrl digit graph lower print punct space upper word xdigit
[[:^class:]]
:代表一个字符,其中[:^class:]
代表一个非[:class:]
中的字符\
:转义字符,用于转义特殊字符,如\*
表示*
本身,\?
表示?
本身,\[
表示[
本身,\]
表示]
本身,
模式匹配的优先级:
[...]
>[[:class:]]
>[[:^class:]]
>\
>*
>?
接下来,我们看一些示例: