shell训练营 | 2. Shell 中的数组应用、参数处理和函数的应用

1,008 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

王志远,微医前端技术部

系列文目录

小节主题文档期待产出补充
Shell 的基本介绍、常用命令以及 Shell 的流程控制juejin.cn/post/714899…
Shell 中的数组应用、参数处理本文
Shell 的函数、模块化、公共函数库
Shell 周边:语言特殊点/调试 Debug 方案/vscode 对 shell 的支持

Shell 中的数组应用、参数处理和函数的应用

shell 之语句

  • 顺序
  • 测试:退出与退出状态、测试命令 test
  • 分支:if-then
  • 循环:for/while/do-while

测试命令(学习分支语句的前提)

参考文档:

状态:$? 和 exit

根据程序是否正常执行(程序退出的状态)进行判断

  • exit:手动退出 shell 的命令
  • exit 10 返回 10 给 shell,返回值非 0 为不正常退出
  • $? 用于判读昂当前 shell 前一个进程是否正常退出(非 0 为不正常退出)

命令:test

tesh 命令可以用于检查文件或者比较值,可用于如下功能(可以用man test查看更具体的命令)

  • 整数比较测试
  • 字符串测试
  • 文件测试

test 测试语句可以简化为[]符号,而[]符号还有扩展写法[[]] ,支持 &&、||、<、>(推荐使用[[]])

字符串测试

两个字符串是否相等:[str1 = str2] 和 [str1 != str2]

#!/bin/bash
str1='a'
str2='a'
if [ $str1 = $str2 ]; then
    echo '等于'

elif [ $str1 != $str2 ]; then
    echo '不等于'
fi

读取字符串长度是否是 0(空字符串):-z

#!/bin/bash
str1='a'
str2=''
if [ -z $str1 ]; then
    echo 'str1 为空字符串'
else
    echo 'str1 不为空字符串'
fi

if [ -z $str2 ]; then
    echo 'str2 为空字符串'
else
    echo 'str2 不为空字符串'
fi
整数比较测试
功能[]中的符号[[]]中的支持
等于-eq 和 = 均支持=
大于等于-ge暂无
大于-gt>
小于等于-le暂无
小于-lt<
不等于-ne!=
#!/bin/bash
a=1
b=2

# if [ $a = $b ]; then
if [ $a -eq $b ]; then
    echo 'a 等于 b'
elif [ $a -ge $b ]; then
    echo 'a 大于等于 b'
elif [ $a -gt $b ]; then
    echo 'a 大于 b'
elif [ $a -le $b ]; then
    echo 'a 小于等于 b'
elif [ $a -lt $b ]; then
    echo 'a 小于 b'
elif [ $a -ne $b ]; then
    echo 'a 不等于 b'
fi

if [[ $a = $b ]]; then
    echo 'a 等于 b'
    # elif [[ $a >= $b ]]; then
    # echo 'a 大于等于 b'
elif [[ $a > $b ]]; then
    echo 'a 大于 b'
# elif [[ $a <= $b ]]; then
#     echo 'a 小于等于 b'
elif [[ $a < $b ]]; then
    echo 'a 小于 b'
elif [[ $a != $b ]]; then
    echo 'a 不等于 b'
fi
文件测试
功能符号例子
-b
-e路径存在,不区分文件和目录test -e [路径] 或 [ -e [路径]]
-d目录是否存在test -d [路径] 或 [ -d [路径]]
-f文件是否存在test -f [路径] 或 [ -f [路径]]
-x文件是否可执行

分支语句

  • 基础 if
  • if-else
  • if-elif
  • 嵌套 if
  • case 语句

基本用法:基础 if

  • 测试语句
  • 命令返回值
if [ 测试条件成立 || 命令返回值为 0 ]; then
相关行为
fi # 结束

实例

if [ $UID = 0 ]; then
    echo " root user "
fi
if [ pwd ]; then
    echo " root user "
fi

基本用法:if-else

if [ 测试条件成立 || 命令返回值为 0 ]; then
相关行为
elif
相关行为
fi # 结束

实例

#!/bin/bash
if [ $UID = 0 ]; then
    echo " root user "
elif
    echo " $UID user "
fi

基本用法:if-elif-else

if [ 测试条件成立 || 命令返回值为 0 ]; then
相关行为
elif [ 测试条件成立 || 命令返回值为 0 ]; then
相关行为
elif
相关行为
fi # 结束

实例

#!/bin/bash
if [ $UID = 0 ]; then
    echo " root user "
elif [ $UID = 501 ]; then
		echo " wangzy user "
else
    echo " $UID user "
fi

基本用法:嵌套 if

#!/bin/bash
if [ 测试条件成立 || 命令返回值为 0 ]; then
	if [ 测试条件成立 || 命令返回值为 0 ]; then
  相关行为
  else
  相关行为
  fi # 结束
else
相关行为
fi # 结束

实例实现:先判断是不是王志远账户,是则再执行对应文件

#!/bin/bash
if [ $UID = 0 ]; then
    echo " root user "
elif [ $UID = 501 ]; then
    if [ -x /Users/wzyan/Documents/selfspace/kkb-down/demo/if/index.sh ]; then
        $(pwd)/index.sh
    else
        echo " wangzy user error $(pwd)"
    fi
else
    if [ $(pwd) = "/Users/wzyan/Documents/selfspace/kkb-down/demo/if" ]; then
        echo " wangzy user  path"
    else
        echo " wangzy user error $(pwd)"
    fi
fi

case 语句

case "$变量" in
"情况 1" )
命令...;;
"情况 2" )
命令...;;
* )
命令...;;
esac

实例实现:先判断是不是王志远账户,是则再执行对应文件

#!/bin/bash
case "$1" in
"start" | "restart")
    echo $0 starting...
    ;;
"stop")
    echo $0 stoping...
    ;;
*)
    echo "$0 传参错误 {start|stop|restart|reload}"
    ;;
esac

循环语句

  • for
  • c 语言风格的 for
  • while
  • util
  • 嵌套循环
  • 使用关键字 break 和 continue

for 循环

注意:

  1. 当使用反引号或者$()执行命令时,其结果会被当作列表处理
  2. 列表中包含多个变量,变量间用空格分隔
  3. 对文本处理时,要用文本查看命令取出文本内容,默认装处理,如果出现空格就会当成多行处理
for 参数 in 列表
do 执行的命令
done #封闭一个循环

实例实现:遍历列表输出

#!/bin/bash
for i in {1..9}
do zzxzxxxzzzzzzzzzzzzzzzzzzzzzzzzzzzxxxxxecho hello; echo $i
done #封闭一个循环
# 读取指定目录下的所有可执行 sh 文件
for sc_name in /etc/profile.d/*.sh
do echo $sc_name; echo $i
done #封闭一个循环

实例实现:读取命令结果进行取出所有 mp3 文件的文件名(basename [文件路径] [文件后缀])

#!/bin/bash
for filename in `ls *.mp3`
do
	mv $filename $(basename $filename .mp3).mp4
done

c 语言风格的 for

for((变量初始化;循环判断条件;变量变化))
do
	循环执行命令
done

实例实现:输出 1-10

#!/bin/bash
for((i=1;i<=10;i++))
do
	echo $i
done

while

特点:直到输入为非 0 才中止

while [test 测试为假时中止]
do
命令
done

实例实现:输出 1-10

#!/bin/bash
a=1 # 小于 10
while [ $a -lt 10 ]
do
((a++)); echo $a;
done

实现死循环

while :; do echo ;done

until

特点:与 while 相反,直到输入为 0 才中止

until [test 测试为真时中止]
do
命令
done

实例实现:输出 1-10

#!/bin/bash
while []
do
命令
done

嵌套循环

找出/etc/profile.d 目录下所有可执行文件

for sc_name in /etc/profile.d/*.sh
do
	echo $sc_name
done

找出/etc/profile.d 目录下所有可执行文件并执行

for sc_name in /Users/wzyan/Documents/selfspace/kkb-down/demo/for/test-x/*.sh; do
    if [ -x $sc_name ]; then
        . $sc_name
    fi
done

使用关键字 break 和 continue

找出/etc/profile.d 目录下所有可执行文件并执行

for num in {1..9}
do
	echo $num
done

实战:处理命令行参数

  • 命令行参数可以使用11 2..10..{10}..{n}进行读取
  • $0 代表脚本名称
  • \*\* 和 @代表所有位置参数
  • $#代表位置参数的数量
for pos in $*; do
    if [ "$pos" = "help" ]; then
        echo $pos
    fi
done