Bash Scripting
简介
记录一下bash脚本编写的东东,可以参考cheatsheet
调试打印¶
在Bash脚本里打开打印,并利用shellprof 来./shellprof ./testcase.sh计算时间。
#!/bin/bash
# 使用 trap 来捕获 DEBUG 信号,每次执行命令前触发
trap 'echo "$BASH_COMMAND"' DEBUG
# 设置调试模式打印前缀PS4,包含时间戳和行号
export PS4='+ $(date "+%Y-%m-%d %H:%M:%S.%3N")\011 '
set -x # 开启调试模式
基础知识¶
参数¶
$?是上一个指令执行的状态值$@代表shell脚本的命令行参数.$1,$2, etc., 分别代表命令行传入的第一个和第二个参数。举例,对于命令./run.sh XXX YYY,$1代表XXX,$2代表YYY。
#匹配并删除最短前缀
str="/path/to/foo.cpp"
echo "${str%.cpp}" # /path/to/foo
echo "${str%.cpp}.o" # /path/to/foo.o
echo "${str%/*}" # /path/to
echo "${str##*.}" # cpp (extension)
echo "${str##*/}" # foo.cpp (basepath)
echo "${str#*/}" # path/to/foo.cpp
echo "${str##*/}" # foo.cpp
在 Bash 脚本中,# 和 ## 符号用于字符串操作,具体用于删除前缀部分:
${str#pattern}:删除变量str中最短匹配pattern的前缀。${str##pattern}:删除变量str中最长匹配pattern的前缀。
例如:
echo "${str##*.}":这行代码使用##删除了最后一个.及其前面的所有内容,从而只保留了文件扩展名cpp。这是因为*匹配所有字符。echo "${str##*/}":这行代码使用##删除了最后一个/及其前面的所有内容,因此只保留了文件名foo.cpp。${str#*/}删除了第一个/之前的部分,结果是path/to/foo.cpp。${str##*/}删除了最后一个/之前的所有部分,结果是foo.cpp。
这两个符号用于简化路径处理和提取文件名等。
变量作用域¶
- Bash 中的变量是 全局变量,也就是说,在脚本中的任何地方都可以访问到这个变量,除非使用 local 关键字将其作用域限制在特定的函数中。
local声明的变量确实限制了它的作用域,但作用域仅限制在当前函数及其子函数(嵌套函数)内。对于嵌套函数,还是共用(读取和修改)上层的local变量。
函数传参¶
- Bash里的函数传参和脚本的命令行参数也是共用
$@和$1等,但是默认是函数的局部变量。 - 如果忘记使用局部变量,这常会导致一个问题:
- 外层的for循环的i被内层函数的for循环i修改导致循环异常。
- 解决方案:需要将内层函数的for循环i定义为local,来与上层的隔离。
其他¶
/dev/null是一个几乎不管向它写入什么,都只返回成功,但是什么都没真的写入的文件。换句话说就是个“无底洞”,扔进去的东西肯定算扔进去了,但是扔进去就看不见了。
Environment¶
# read
SCRIPT_DIR="$(dirname $0)"
# set
export HOSTNAME="$(hostname)"
# check Environment
if [[ -z "${ITHEMAL_HOME}" ]]; then
echo "ITHEMAL_HOME environment variable must be set!"
exit 1
fi
实例¶
判断docker是否启动
尝试获取sudo权限
重连或者创建一个到名称为$1的tmux窗口
参考文献¶
无