前阵子写了不少 bash 脚本,有些代码片段值得一记。有以下几项内容:
- 获取当前脚本文件所在路径
- 字符串 startsWith 和 endsWith
- 判断字符串内容是否是数字
- 获取字符串的子串
- if 语句的几个判断条件
获取当前脚本文件所在的路径
用户执行脚本时,用户所在的目录,也就是 current working directory,可以通过执行 pwd
或者 bash 的内置变量 $PWD
获取。
有时用户执行脚本时,需要拿到脚本文件本身的路径,就稍微麻烦一些。
CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
字符串 startsWith 和 endsWith
使用 *
号来实现这两个小功能。
如下,判断是否以 sub_string
开头。
if [[ $var == sub_string* ]]; then
printf '%s\n' "var starts with sub_string."
fi
if [[ $var != sub_string* ]]; then
printf '%s\n' "var does not start with sub_string."
fi
判断是否以 sub_string
结尾
if [[ $var == *sub_string ]]; then
printf '%s\n' "var ends with sub_string."
fi
if [[ $var != *sub_string ]]; then
printf '%s\n' "var does not end with sub_string."
fi
isNumber
判断字符串的内容是否是个数字,比如 "1234"
为真,"abcd"
或 "12abcd"
为假。
isNumber() {
local str="$1"
local re="^[0-9]+$"
[[ "$str" =~ $re ]]
}
使用 isNumber
的例子:
#!/bin/bash
isNumber() {
local str="$1"
local re="^[0-9]+$"
[[ "$str" =~ $re ]]
}
tests() {
isNumber "$1" && echo "yes" || echo "no"
}
tests ""
tests "abc"
tests "abc123"
tests "1acb23"
tests "123"
tests "455"
输出结果:
no no no no yes yes
如果要允许带小数点的格式,那么要把上述代码中的正则表达式换成 ^[0-9]+([.][0-9]+)?$
。
Stackoverflow – How do I test if a variable is a number in Bash?
获取字符串的子串
有很多方法可以做字符串分割,比如用 cut
命令,awk
命令等等。这里记录的是我一直记不住的一个代码片段。
比如一个字符串变量是 var=hello.world-1234.txt
,我们想要根据字符串中的点和横线来分割,获取子字符串。
${var#pattern}
从字符串开始位置,去除最短匹配 pattern 的部分。例如 ${var#*.}
,pattern 中的星号是通配符,结果就是匹配到第一个 .
之前的部分被去掉,获取到的字符串是 world-1234.txt
。
${var##pattern}
从字符串开始位置,去除最长匹配 pattern 的部分。${var%pattern}
从字符串结尾位置,去除最短匹配 pattern 的部分。${var%%pattern}
从字符串结尾位置,去除最长匹配 pattern 的部分。
var=hello.world-1234.txt
echo "${var#*.}"
echo "${var##*.}"
echo "${var%.*}"
echo "${var%%.*}"
结果是
world-1234.txt // 从前向后截掉最短匹配 *. 的子串
txt // 从前向后截掉最长匹配 *. 的字串
hello.world-1234 // 从后向前截掉最短匹配 .* 的内容
hello // 从后向前截掉最长匹配 .* 的内容
如果想把 hello.world
截取出来,可以用 ${var%-*}
。由于 var
里只有一个 -
,所以从前往后或者从后往前,找到的都是一个位置,${var%%-*}
同样得到 hello.world
。
if 判断条件
-e 文件是否存在(万物皆文件)
-d 是否是目录并且存在
-s 文件是否存在并且大小不为 0
-f 文件是否存在并且是普通文件
-h 文件是否存在并且是符号链接
-L 文件是否存在并且是符号链接
-z 字符串长度是否为 0
-n 字符串长度是否不为 0
要注意以下几点:
- 不论是普通文件,软链接,目录,块设备等等,都是「文件」,
-e
测试都为真。 -f
测试一个普通文件,或者一个软链接,结果都为真。要确定是否是软链接,用-h
或-L
。