跳至主要內容

Bash脚本笔记

Alooc...大约 12 分钟后端技术BashBash

https://wangdoc.com/bash/intro.htmlopen in new window
https://github.com/wangdoc/bash-tutorialopen in new window

1. 变量

2. 函数

3. 循环

4. 顺序

5. 特殊符号

6. 正则表达式

bash

1. 简介

  1. shenbang行
# 脚本第一行通常是指定解释器
#! /bin/bash
  1. 执行权限和路径
# 给脚本赋权
chmod 744 scaript.sh
  1. env命令

    env指向 /usr/bin/env

  2. 注释

# 注释
  1. 脚本参数
  • $0 脚本文件名
  • $1 ~ $9 对应脚本的第一到第九个参数
  • $# 参数的总数
  • $@ 全部的参数,参数之间使用空格分隔
  • $* 全部的参数
  1. shift命令

? shift命令可以改变脚本参数,每次执行都会移除脚本当前的第一个参数

#! /bin/bash

echo "一共输入了$#个参数"

while [ "$1" != ""];do
	echo "剩下$#个参数"
	echo "参数:$1"
	shift
done
  1. getopts命令

? 取出脚本所有的带有前置连词线(-)的参数

  1. 配置项参数中止符

? -- 强制后面的变量只能是路径

  1. exit命令

? 用于终止当前脚本的执行,并向shell返回一个退出值

  1. 命令执行结果

? 命令执行结束后,会有一个返回值。

? 0表示执行成功,非0(通常是1) 表示执行失败。

? 环境变量$? 可以读取前一个命令的返回值

  1. source命令

? 用于执行一个脚本,通常用于重新加载一个配置文件

  1. 别名,alias 命令

2. 基本语法

  1. echo命令

? 屏幕输出一行文本,可以将该命令的参数原样输出

? 若输出多行,需将多行文本放在引号里面

? 1.1 -n参数

? 取消末尾的回车符

? 1.2 -e参数

? 会解释引号里面的特殊字符

  1. 命令格式
command [arg1 ... [argN]]
  1. 空格

? bash使用空格区分不同的参数

  1. 分号

? 分号是命令的结束符,使得一行可以放置多个命令,上一个命令执行结束后,再执行第二个命令

  1. 命令的组合符 && ||

  2. type命令

    判断命令的来源

  3. 快捷键

  • Ctrl + L:清除屏幕并将当前行移到页面顶部。
  • Ctrl + C:中止当前正在执行的命令。
  • Shift + PageUp:向上滚动。
  • Shift + PageDown:向下滚动。
  • Ctrl + U:从光标位置删除到行首。
  • Ctrl + K:从光标位置删除到行尾。
  • Ctrl + D:关闭 Shell 会话。
  • :浏览已执行命令的历史记录。

3. 模式扩展

  1. 简介

    Shell 接收到用户输入的命令以后,会根据空格将用户的输入,拆分成一个个词元(token)。然后,Shell 会扩展词元里面的特殊字符,扩展完成后才会调用相应的命令。

    Bash 一共提供八种扩展:

    • 波浪线扩展
    • ? 字符扩展
    • * 字符扩展
    • 方括号扩展
    • 大括号扩展
    • 变量扩展
    • 子命令扩展
    • 算术扩展
  2. 波浪线扩展

    波浪线~会自动扩展成当前用户的主目录。

  3. ? 字符扩展

    ?字符代表文件路径里面的任意单个字符,不包括空字符。

  4. * 字符扩展

    *字符代表文件路径里面的任意数量的任意字符,包括零个字符。

  5. 方括号扩展

    方括号扩展的形式是[...],只有文件确实存在的前提下才会扩展。如果文件不存在,就会原样输出。括号之中的任意一个字符。比如,[aeiou]可以匹配五个元音字母中的任意一个。

    [start-end] 表示匹配一个连续的范围。比如,[a-c]等同于[abc][0-9]匹配[0123456789]

  6. 大括号扩展

    大括号扩展{...}表示分别扩展成大括号里面的所有值,各个值之间使用逗号分隔。比如,{1,2,3}扩展成1 2 3

    {start..end},表示扩展成一个连续序列。比如,{a..z}可以扩展成26个小写英文字母。

  7. 变量扩展

    Bash 将美元符号$开头的词元视为变量,将其扩展成变量值

  8. 子命令扩展

    $(...)可以扩展成另一个命令的运行结果,该命令的所有输出都会作为返回值。

    $ echo $(date)
    Tue Jan 28 00:01:13 CST 2020
    
  9. 算术扩展

    $((...))可以扩展成整数运算的结果

    $ echo $((2 + 2))
    4
    
  10. 字符类

    [[:class:]]表示一个字符类,扩展成某一类特定字符之中的一个。常用的字符类如下。

    • [[:alnum:]]:匹配任意英文字母与数字
    • [[:alpha:]]:匹配任意英文字母
    • [[:blank:]]:空格和 Tab 键。
    • [[:cntrl:]]:ASCII 码 0-31 的不可打印字符。
    • [[:digit:]]:匹配任意数字 0-9。
    • [[:graph:]]:A-Z、a-z、0-9 和标点符号。
    • [[:lower:]]:匹配任意小写字母 a-z。
    • [[:print:]]:ASCII 码 32-127 的可打印字符。
    • [[:punct:]]:标点符号(除了 A-Z、a-z、0-9 的可打印字符)。
    • [[:space:]]:空格、Tab、LF(10)、VT(11)、FF(12)、CR(13)。
    • [[:upper:]]:匹配任意大写字母 A-Z。
    • [[:xdigit:]]:16进制字符(A-F、a-f、0-9)。
  11. 使用注意点

    通配符有一些使用注意点:

    (1)通配符是先解释,再执行。

    (2)文件名扩展在不匹配时,会原样输出。

    (3)只适用于单层路径。

    (4)文件名可以使用通配符。

  12. 量词语法

    • ?(pattern-list):匹配零个或一个模式。
    • *(pattern-list):匹配零个或多个模式。
    • +(pattern-list):匹配一个或多个模式。
    • @(pattern-list):只匹配一个模式。
    • !(pattern-list):匹配零个或一个以上的模式,但不匹配单独一个的模式。
  13. shopt命令

    shopt命令可以调整 Bash 的行为。它有好几个参数跟通配符扩展有关。

    # 打开某个参数
    $ shopt -s [optionname]
    
    # 关闭某个参数
    $ shopt -u [optionname]
    
    # 查询某个参数关闭还是打开
    $ shopt [optionname]
    

4. 引号和转义

  1. 转义

    些字符在 Bash 里面有特殊含义(比如$&*)。

    如果想要原样输出这些特殊字符,就必须在它们前面加上反斜杠,使其变成普通字符。这就叫做“转义”(escape)。

    $ echo \$date
    $date
    
    • \a:响铃
    • \b:退格
    • \n:换行
    • \r:回车
    • \t:制表符
  2. 单引号

    单引号用于保留字符的字面含义,各种特殊字符在单引号里面,都会变为普通字符,比如星号(*)、美元符号($)、反斜杠(\)等。

  3. 双引号

    双引号比单引号宽松,大部分特殊字符在双引号里面,都会失去特殊含义,变成普通字符。

    但是,三个特殊字符除外:美元符号($)、反引号(```)和反斜杠(\)。这三个字符在双引号之中,依然有特殊含义,会被 Bash 自动扩展。

    双引号还有一个作用,就是保存原始命令的输出格式。

    # 单行输出
    $ echo $(cal)
    一月 2020 日 一 二 三 四 五 六 1 2 3 ... 31
    
    # 原始格式输出
    $ echo "$(cal)"
          一月 2020
    日 一 二 三 四 五 六
              1  2  3  4
     5  6  7  8  9 10 11
    12 13 14 15 16 17 18
    19 20 21 22 23 24 25
    26 27 28 29 30 31
    
    
  4. here文档

    它的格式分成开始标记(<< token)和结束标记(token)。

  5. here字符串

    作用是将字符串通过标准输入,传递给命令。

    $ cat <<< 'hi there'
    # 等同于
    $ echo 'hi there' | cat
    

5. 变量

  1. 环境变量
  2. 自定义变量

6. 字符串操作

  1. 字符串的长度

    ${#varname}
    
  2. 子字符串

    ${varname:offset:length}
    
$ count=frogfootman
$ echo ${count:4:4}
foot
  1. 搜索和替换

    (1)字符串头部的模式匹配。

    (2)字符串尾部的模式匹配。

    (3)任意位置的模式匹配。

  2. 改变大小写

    # 转为大写
    ${varname^^}
    
    # 转为小写
    ${varname,,}
    

7. 算术运算

8. 行操作

9. 目录堆栈

10. 脚本入门

11. read命令

12. 条件判断

if commands; then
  commands
[elif commands; then
  commands...]
[else
  commands]
fi
if test $USER = "foo"; then
  echo "Hello foo."
else
  echo "You are not foo."
fi
# 写法一
test expression

# 写法二
[ expression ]

# 写法三
[[ expression ]]
# 写法一
if test -e /tmp/foo.txt ; then
  echo "Found foo.txt"
fi

# 写法二
if [ -e /tmp/foo.txt ] ; then
  echo "Found foo.txt"
fi

# 写法三
if [[ -e /tmp/foo.txt ]] ; then
  echo "Found foo.txt"
fi
文件判断
  • [ -a file ]:如果 file 存在,则为true
  • [ -b file ]:如果 file 存在并且是一个块(设备)文件,则为true
  • [ -c file ]:如果 file 存在并且是一个字符(设备)文件,则为true
  • [ -d file ]:如果 file 存在并且是一个目录,则为true
  • [ -e file ]:如果 file 存在,则为true
  • [ -f file ]:如果 file 存在并且是一个普通文件,则为true
  • [ -g file ]:如果 file 存在并且设置了组 ID,则为true
  • [ -G file ]:如果 file 存在并且属于有效的组 ID,则为true
  • [ -h file ]:如果 file 存在并且是符号链接,则为true
  • [ -k file ]:如果 file 存在并且设置了它的“sticky bit”,则为true
  • [ -L file ]:如果 file 存在并且是一个符号链接,则为true
  • [ -N file ]:如果 file 存在并且自上次读取后已被修改,则为true
  • [ -O file ]:如果 file 存在并且属于有效的用户 ID,则为true
  • [ -p file ]:如果 file 存在并且是一个命名管道,则为true
  • [ -r file ]:如果 file 存在并且可读(当前用户有可读权限),则为true
  • [ -s file ]:如果 file 存在且其长度大于零,则为true
  • [ -S file ]:如果 file 存在且是一个网络 socket,则为true
  • [ -t fd ]:如果 fd 是一个文件描述符,并且重定向到终端,则为true。 这可以用来判断是否重定向了标准输入/输出/错误。
  • [ -u file ]:如果 file 存在并且设置了 setuid 位,则为true
  • [ -w file ]:如果 file 存在并且可写(当前用户拥有可写权限),则为true
  • [ -x file ]:如果 file 存在并且可执行(有效用户有执行/搜索权限),则为true
  • [ file1 -nt file2 ]:如果 FILE1 比 FILE2 的更新时间最近,或者 FILE1 存在而 FILE2 不存在,则为true
  • [ file1 -ot file2 ]:如果 FILE1 比 FILE2 的更新时间更旧,或者 FILE2 存在而 FILE1 不存在,则为true
  • [ FILE1 -ef FILE2 ]:如果 FILE1 和 FILE2 引用相同的设备和 inode 编号,则为true
字符串判断
  • [ string ]:如果string不为空(长度大于0),则判断为真。
  • [ -n string ]:如果字符串string的长度大于零,则判断为真。
  • [ -z string ]:如果字符串string的长度为零,则判断为真。
  • [ string1 = string2 ]:如果string1string2相同,则判断为真。
  • [ string1 == string2 ] 等同于[ string1 = string2 ]
  • [ string1 != string2 ]:如果string1string2不相同,则判断为真。
  • [ string1 '>' string2 ]:如果按照字典顺序string1排列在string2之后,则判断为真。
  • [ string1 '<' string2 ]:如果按照字典顺序string1排列在string2之前,则判断为真。
整数判断
  • [ integer1 -eq integer2 ]:如果integer1等于integer2,则为true
  • [ integer1 -ne integer2 ]:如果integer1不等于integer2,则为true
  • [ integer1 -le integer2 ]:如果integer1小于或等于integer2,则为true
  • [ integer1 -lt integer2 ]:如果integer1小于integer2,则为true
  • [ integer1 -ge integer2 ]:如果integer1大于或等于integer2,则为true
  • [ integer1 -gt integer2 ]:如果integer1大于integer2,则为true
正则判断
[[ string1 =~ regex ]]
#!/bin/bash

INT=-5

if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
  echo "INT is an integer."
  exit 0
else
  echo "INT is not an integer." >&2
  exit 1
fi
  • AND运算:符号&&,也可使用参数-a
  • OR运算:符号||,也可使用参数-o
  • NOT运算:符号!

Bash 还提供了((...))作为算术条件,进行算术运算的判断

$ command1 && command2
$ command1 || command2
case expression in
  pattern )
    commands ;;
  pattern )
    commands ;;
  ...
esac

13. 循环

while condition; do
  commands
done
until condition; do
  commands
done
for variable in list
do
  commands
done
for (( expression1; expression2; expression3 )); do
  commands
done
for number in 1 2 3 4 5 6
do
  echo "number is $number"
  if [ "$number" = "3" ]; then
    break
  fi
done
select name
[in list]
do
  commands
done

14. 函数

# 第一种
fn() {
  # codes
}

# 第二种
function fn() {
  # codes
}
  • $1~$9:函数的第一个到第9个的参数。
  • $0:函数所在的脚本名。
  • $#:函数的参数总数。
  • $@:函数的全部参数,参数之间使用空格分隔。
  • $*:函数的全部参数,参数之间使用变量$IFS值的第一个字符分隔,默认为空格,但是可以自定义。

return命令用于从函数返回一个值。函数执行到这条命令,就不再往下执行了,直接返回了。

15. 数组

ARRAY[INDEX]=value
 echo ${array[i]}  
echo ${foo[@]}
echo ${foo[0]}
${#array[*]}
${#array[@]}

${!array[@]}${!array[*]},可以返回数组的成员序号,即哪些位置是有值的。

${array[@]:position:length}的语法可以提取数组成员。

数组末尾追加成员,可以使用+=赋值运算符。它能够自动地把值追加到数组末尾。

删除一个数组成员,使用unset命令。

unset foo[2]

declare -A可以声明关联数组。

16. set命令,shopt命令

17. 脚本除错

  • bash -x

18. mktemp 命令,trap命令

直接运行mktemp命令,就能生成一个临时文件。-d参数可以创建一个临时目录。

trap命令用来在 Bash 脚本中响应系统信号。

$ trap -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX
$ trap [动作] [信号1] [信号2] ...
  • HUP:编号1,脚本与所在的终端脱离联系。
  • INT:编号2,用户按下 Ctrl + C,意图让脚本终止运行。
  • QUIT:编号3,用户按下 Ctrl + 斜杠,意图退出脚本。
  • KILL:编号9,该信号用于杀死进程。
  • TERM:编号15,这是kill命令发出的默认信号。
  • EXIT:编号0,这不是系统信号,而是 Bash 脚本特有的信号,不管什么情况,只要退出脚本就会产生。
$ trap 'rm -f "$TMPFILE"' EXIT

19. 启动环境

为了方便 Debug,有时在启动 Bash 的时候,可以加上启动参数。

  • -n:不运行脚本,只检查是否有语法错误。
  • -v:输出每一行语句运行结果前,会先输出该行语句。
  • -x:每一个命令处理之前,先输出该命令,再执行该命令。
$ bash -n scriptname
$ bash -v scriptname
$ bash -x scriptname

20. 命令提示符

  • 可以自定义
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.5