Bash脚本语言入门记录(一)

0 阅读3分钟

Bash 是 Linux 和 Mac 的默认 Shell(命令行环境),可以把多个命令组合自动执行,用于自动化运维、日志分析、备份、部署等任务。

本文参考:

一、Bash 的基本语法

  • bash 是由多个命令组合而成,bash中的基本命令格式如下:
$ command [ arg1 ... [ argN ]]
  • 如果命令过长,可通过反斜杠(\)换行:
$ echo foo bar

# 等同于
$ echo foo \
bar
  • 分号(;)是命令的结束符,使得一行可以放置多个命令,上一个命令执行结束后,再执行第二个命令:
$ clear; ls
# 使用分号时,第二个命令总是接着第一个命令执行,不管第一个命令执行成功或失败。
  • 除了分号,Bash 还提供两个命令组合符&&||,允许更好地控制多个命令之间的继发关系:
Command1 && Command2 # 如果Command1命令运行成功,则继续运行Command2命令
Command1 || Command2 # 如果Command1命令运行失败,则继续运行Command2命令

二、Bash 变量

1、环境变量

环境变量是 Bash 环境自带的变量,进入 Shell 时已经定义好了,可以直接使用,env命令或printenv命令,可以显示所有环境变量。

查看单个环境变量的值,可以使用printenv命令或echo命令:

$ printenv PATH #无需添加$
# 或者
$ echo $PATH #需要添加$

2、自定义变量

用户创建变量的时候,变量名必须遵守下面的规则。

  • 字母、数字和下划线字符组成。
  • 第一个字符必须是一个字母或一个下划线,不能是数字。
  • 不允许出现空格和标点符号。

变量声明的语法如下:

variable=value

等号左边是变量名,右边是变量。如果变量包含空格,需要将变量包含在双引号中:

myvar="hello world"

变量支持多种数据来源赋值:

a=z                     # 变量 a 赋值为字符串 z
b="a string"            # 变量值包含空格,就必须放在引号里面
c="a string and $b"     # 变量值可以引用其他变量的值
d="\t\ta string\n"      # 变量值可以使用转义字符
e=$(ls -l foo.txt)      # 变量值可以是命令的执行结果
f=$((5 * 7))            # 变量值可以是数学运算的结果

读取变量只需要在变量名前加$即可:

$ foo=bar
$ echo $foo

如果变量的值本身也是变量,可以使用${!varname}的语法,读取最终的值

$ myvar=USER
$ echo $myvar
USER

$ echo ${!myvar}
root

三、Bash 脚本入门

1、Shebang 行

脚本的第一行通常是指定解释器,即这个脚本必须通过什么解释器执行。这一行以#!字符开头,后面跟脚本解释器的位置,Bash 脚本的解释器一般是/bin/sh/bin/bash

2、脚本参数

调用脚本的时候,脚本文件名后面可以带有参数,例如:

$ script.sh word1 word2 word3

脚本文件内部,可以使用特殊变量,引用这些参数。

  • $0:脚本文件名,即script.sh
  • $1~$9:对应脚本的第一个参数到第九个参数。
  • $#:参数的总数。
  • $@:全部的参数,参数之间使用空格分隔。

getopts 命令

getopts命令用在脚本内部,可以解析复杂的脚本命令行参数,通常与while循环一起使用,取出脚本所有的带有前置连词线(-)的参数。

getopts optstring name
# 例如 getopts 'lha:' OPTION
  • 第一个参数optstring是字符串,给出脚本所有的连词线参数,比如,某个脚本可以有三个连词线参数-l-h-a,其中只有-a可以带有参数值,而-l-h是开关参数,那么getopts的第一个参数写成lha:,带参数值的连词线参数后要加:
  • 第二个参数name是一个变量名,用来保存当前取到的连词线参数,即lha

使用示例:

while getopts 'lha:' OPTION; do
  case "$OPTION" in
    l)
      echo "linuxconfig"
      ;;

    h)
      echo "h stands for h"
      ;;

    a)
      avalue="$OPTARG" # 环境变量 $OPTARG 保存的就是当前连词线参数的参数值。
      echo "The value provided is $OPTARG"
      ;;
    ?)  # 如果用户输入了没有指定的参数(比如 -x),那么 OPTION 等于 ? 
      echo "script usage: $(basename $0) [-l] [-h] [-a somevalue]" >&2
      exit 1
      ;;
  esac
done

需要注意的是,只要遇到不带连词线的参数,getopts就会执行失败,从而退出while循环,比如,getopts可以解析command -l foo,但不可以解析command foo -l

shift 命令

shift命令可以改变脚本参数,每次执行都会移除脚本当前的第一个参数($1),使得后面的参数向前一位,即$2变成$1$3变成$2$4变成$3,以此类推。

shift命令可以接受一个整数作为参数,指定所要移除的参数个数,默认为1:

shift 3

在使用getopts命令时,可以使用如下方式,将连词线参数去除掉:

shift "$(($OPTIND - 1))"

变量$OPTINDgetopts开始执行前是1,然后每次执行就会加1。等到退出while循环,就意味着连词线参数全部处理完毕。这时,$OPTIND - 1就是已经处理的连词线参数个数

if 语句

if是最常用的条件判断结构,只有符合给定条件时,才会执行指定的命令。它的语法如下:

if commands; then
  commands
[elif commands; then
  commands...]
[else
  commands]
fi

test 命令

if语句中使用test命令作为判断条件:

# 写法一
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

test 命令的相关参数如下:

操作符描述示例
-e文件是否存在[ -e file.txt ]
-f是普通文件[ -f /path/to/file ]
-d是目录[ -d /path/to/dir ]
-r可读[ -r file.txt ]
-w可写[ -w file.txt ]
-x可执行[ -x script.sh ]
-s文件大小 >0[ -s logfile ]
-L是符号链接[ -L symlink ]
-z STRING字符串为空[ -z "$var" ]
-n STRING字符串非空[ -n "$var" ]
STRING1 = STRING2字符串相等[ "$var1" = "$var2" ]
STRING1 != STRING2字符串不等[ "$var1" != "$var2" ]

case 结构

expression是一个表达式,pattern是表达式的值或者一个模式,可以有多条,用来匹配多个值,每条以两个分号(;)结尾:

case expression in
  pattern )
    commands ;;
  pattern )
    commands ;;
  ...
esac

while 循环

while循环有一个判断条件,只要符合条件,就不断循环执行指定的语句。

while condition; do
  commands
done

循环语句中也支持continuebreak语句,使用逻辑和其他语言一样。

for...in 循环

for...in循环用于遍历列表的每一项

for variable in list; do
  commands
done

以遍历当前文件夹下的所有png文件:

for i in *.png; do
  ls -l $i
done