Shell 脚本零碎笔记2

一个纯bash实现外部命令的脚本集合

读取文件到一个字符串中

替代 cat 命令.

1
file_data="$(<"file")"

创建一个空文件

替代 touch.

1
2
# 简短的方式.
>file

值得参考的基础教程:阮一峰 Bash 脚本教程

字符串处理

字符串提取子串
${varname:offset:length}
返回变量$varname的子字符串,从位置offset开始(从0开始计算),长度为length。

1
2
3
$ count=frogfootman
$ echo ${count:4:4}
foot
1
2
3
4
5
## test.jpg 删除后缀.jpg 返回 test
${filename%.*}
## ${branch#*/} 表示删除 $branch 变量中第一个斜杠(/)及其左侧的所有字符
$branch=origin/test
${branch#*/}=test

文件名仅允许字母、数字、横杠与下划线的组合

1
2
3
4
5
6
if [[ ${filename} =~ ^[a-zA-Z0-9_-]*[.] ]];then
echo -e "\033[32m---文件名校验ok---\033[0m"
else
echo -e "\033[31m ERROR:有特殊字符、请检查!\033[0m" && exit -1
fi

长度

1
2
`${#VAR}`: 字符变量的长度.
`${#ARR[@]}` : 数组的长度.

改变大小写

参数 它将做什么?
${VAR^} 大写第一个字符.
${VAR^^} 大写所有字符.
${VAR,} 小写第一个字符.
${VAR,,} 小写所有字符.
${VAR~} 反转第一个字符.
${VAR~~} 反转所有字符.

花括号展开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 符号: {<START>..<END>}

# 打印 1-100 之间的数字.
echo {1..100}

# 打印一个范围内的浮点数.
echo 1.{1..9}

# 打印a-z间的字符.
echo {a..z}
echo {A..Z}

# 嵌套.
echo {A..Z}{0..9}

# 打印用零填充的数字.
echo {01..100}

# 更改步长.
# 符号: {<START>..<END>..<INCREMENT>}
echo {1..10..2} # 每次增加2.

释伴声明

使用 #!/usr/bin/env bash 而不是 #!/bin/bash.

  • 前者搜索用户的 PATH 以查找 bash 二进制文件.
  • 后者假设它始终安装在 /bin/ 目录,可能导致问题.
1
2
3
4
5
6
7
# 正确的方式:

#!/usr/bin/env bash

# 错误的方式:

#!/bin/bash

命令替换

使用 $()而不是 ` `.

1
2
3
4
5
6
7
8
# 正确的方式.
var="$(command)"

# 错误的方式.
var=`command`

# $() 很容易嵌套,而``不能.
var="$(command "$(command)")"

获取系统的主机名

1
2
3
4
5
"$HOSTNAME"

# NOTE: 这个变量可能是空的.
# (可选):将失败调用设置为hostname命令
"${HOSTNAME:-$(hostname)}"

获取操作系统的架构(32位或64位)

1
"$HOSTTYPE"

获取操作系统/内核的名称

这可用于条件判断不同的操作系统,而无需调用uname

1
"$OSTYPE"

获取当前的工作目录

这是内置pwd的替代方案。

1
"$PWD"

获取脚本运行的秒数

1
"$SECONDS"

进度条

这是一种绘制进度条的简单方法,无需在函数本身中使用for循环。

示例函数:

1
2
3
4
5
6
7
8
9
10
11
12
bar() {
# 用法: bar 1 10
# ^----- 已经完成的百分比 (0-100).
# ^--- 字符总长度.
((elapsed=$1*$2/100))

# 创建空格表示的进度条
printf -v prog "%${elapsed}s"
printf -v total "%$(($2-elapsed))s"

printf '%s\r' "[${prog// /-}${total}]"
}

示例用法:

1
2
3
4
5
6
7
8
9
for ((i=0;i<=100;i++)); do
# 纯粹的暂停动作 (为了本例可以更好的演示).
(:;:) && (:;:) && (:;:) && (:;:) && (:;:)

# Print the bar.
bar "$i" "10"
done

printf '\n'