摘自 这些必备的 Linux shell知识你都掌握了吗 | Linux 学习

1. 入参和默认变量

/root/sh-utils/test.sh para1 para2 para3
$0                     $1    $2    $3
脚本名                 第一个参数   第三个参数
  • $0:执行的脚本名
  • $1第一个参数
  • $2第二个参数
  • $#:脚本后面传入的参数个数
  • $@所有参数,并且可以被遍历
  • $*所有参数,不加引号时与$@相同,具体区别请移步 参考文章
  • $?:上一条命令的退出状态
  • 两个$:当前脚本的进程 ID

2. 变量

使用=给变量赋值

para1="hello world"  # 字符串直接赋给变量 para1

注意=两边不能有空格,等号右边有空格的字符串也必须用引号括起来

使用unset取消变量

unset para1

使用变量时,需要在变量前添加$,或者变量名两边添加{}

#!/bin/bash
para1="hello world"

echo "para1 is $para1"
echo "para1 is ${para1}!"

------
para1 is hello world
para1 is hello world!

3. 命令执行

#!/bin/bash

# save command output into var
hostname=`hostname`
echo $hostname

# call command in string
echo "Current path is $(pwd)"

# use double (()) to calculate an expression
echo "36+52=$((36+52))"

# command as a string
kernel="uname -r"    
echo "kernel is $($kernel)"

# several commands as a string
cmd="ls;pwd"
echo "$(eval $cmd)"

------
centos-2
Current path is /root/GithubProjects/sh-utils
36+52=88
kernel is 3.10.0-862.14.4.el7.x86_64
24-bit-color.sh
docker-k8s-images.sh
export-http-proxy.sh
get-wechat-cover.sh
ssr.sh
start-goland.sh
test.sh
tmux-tools
/root/GithubProjects/sh-utils

4. 条件分支

if 语句

一般来说,如果命令成功执行,则其返回值为0,因此可通过下面的方式判断上一条命令的执行结果

if [ $? -eq 0 ]
then
    echo "success"
elif [ $? -eq 1 ]
then
    echo "failed,code is 1"
else
    echo "other code"
fi

case 语句

case语句的使用方法如下:

name="aa"
name="aa"
case $name in
    "aa")
    echo "name is $name"
    ;;
    "")
    echo "name is empty"
    ;;
    "bb")
    echo "name is $name"
    ;;
    *)
    echo "other name"
    ;;
esac

需要注意以下几点:

  • []前面要有空格,里面是逻辑表达式
  • if elif后面要跟then,之后才是要执行的语句
  • 如果想打印上一条命令的执行结果,最好的做法是$?赋给一个变量,因为一旦执行了一条命令,$?的值就可能会变
  • case语句的每个分支最后以两个;;结尾,最后是esac

使用多个条件

有两种写法:

if [ 10 -gt 5 -o 10 -gt 4 ];then
        echo "10>5 or 10>4"
fi
# 或者
if [ 10 -gt 5 ] || [ 10 -gt 4 ];then
        echo "10>5 or 10>4"
fi
  • -a,同&&,表示
  • -o,同||,表示
  • !,表示

整数判断

  • -eq:两数是否相等
  • -ne:两数是否不等
  • -gt:前者是否大于后者
  • -lt:前者是否小于后者
  • -ge:前者是否大于等于后者
  • -le:前者是否小于等于后者

文件目录判断

  • -f $filename:是否为文件
  • -e $filename:是否存在
  • -d $filename:是否为目录
  • -s $filename:文件存在且不为空
  • ! -s $filename:文件是否为空

5. 循环

for in

遍历输出脚本的参数

# 遍历输出脚本的参数
for i in $@; do
    echo $i
done

还可以指定循环变量范围

for i in {1..5}; do
    echo "Welcome $i"
done

在此基础上指定循环步长

for i in {5..15..3}; do
    echo "number is $i"
done

for do

for ((i = 0 ; i < 10 ; i++)); do
    echo $i
done

while do

while [ "$ans" != "yes" ]
do
    read -p "please input yes to exit loop: " ans
done

until do

ans="yes"
until [ "$ans" != "yes" ]
do
    read -p "please input yes to continue loop: " ans
done

6. 函数

函数定义如下:

myfunc()
{
    echo "Hello! $1"
}

或者:

function myfunc()
{
    echo "Hello! $1"
}

函数调用:

para1="abelsu7"
myfunc $para1

7. 返回值

通常函数的return返回值只支持0-255,因此想要获得其他形式的返回值,可以通过下面的方式:

function myfunc()
{
    local myresult="some value"
    echo $myresult
}
val=$(myfunc) # val 的值为 some value

通过return的方式适用于判断函数的执行是否成功

function myfunc()
{
    # do something
    return 0
}

if myfunc;then
    echo "success"
else
    echo "failed"
fi

8. 注释

#!/bin/bash

# 这是单行注释

: << !
注释 1
注释 2
注释 3
!

: '
注释 1
注释 2
注释 3
'

: << EOF
注释 1
注释 2
注释 3
EOF

: << 字符 # 数字或者字符均可
注释 1
注释 2
注释 3
字符 # 要与之前的字符相同

9. 日志保存

脚本执行后免不了要记录日志,常用的方法是重定向

方式一,将标准输出保存到文件中,并在控制台打印标准错误

./test.sh > log.dat

方式二,将标准输出和标准错误都保存到日志文件中

./test.sh > log.dat 2>&1

方式三,保存日志文件的同时,也输出到控制台

./test.sh |tee log.dat

10. 脚本执行

./test.sh      # 最常见的执行方式
sh test.sh     # 在子进程中执行
sh -x test.sh  # 会在终端打印执行的命令,适合调试
source test.sh # 在父进程中执行
. test.sh      # 不需要赋予执行权限,临时执行

11. 脚本退出码

很多时候我们需要获取脚本的执行结果,即退出状态。通常0表示执行成功,而非0表示执行失败

为了获得退出码,我们需要使用exit,例如:

#!/bin/bash
function myfun()
{
    if [ $# -lt 2 ]
    then
       echo "para num error"
       exit 1
    fi
    echo "ok"
    exit 2
}
if [ $# -lt 1 ]
then
    echo "para num error"
    exit 1
fi
returnVal=`myfun aa`
echo "end shell"
exit 0

这里需要注意的是,使用:

returnVal=`myfun aa`

这样的语句来执行函数,即使函数里面有exit,它也不会退出脚本执行,而只是会退出该函数。这是因为exit是退出当前进程,而这种方式执行函数,相当于fork了一个子进程,因此不会退出当前脚本。

所以无论你的函数参数是什么,最后都会打印:

./test.sh;echo $?
0

参考文章

  1. 这些必备的 Linux Shell 知识你都掌握了吗 | Linux 学习
  2. 如何理解 Linux shell中“2>&1”?| 编程珠玑
  3. Shell $* 和 $@ 的区别 | C 语言中文网
  4. Shell $* 与 $@ 的区别 | 博客园
  5. linux bash shell 中,单引号、 双引号,反引号(``)的区别及各种括号的区别 | CSDN
  6. 【Shell】单行注释和多行注释 | 博客园