Shell脚本编程 | 青训营笔记

75 阅读2分钟

Shell脚本编程

变量

类型作用域声明方式规范
自定义变量当前shell=字符串、整型、浮点型、日期型
环境变量当前shell及其子shellexport、declare -x
系统环境变量所有shell启动加载

declare [+/-] 选项 变量

选项含义
-给变量设定类型属性
+取消变量的类型属性
-a将变量声明为数组类型
-i将变量声明为整数类型
-x将变量声明为环境变量
-r将变量声明为只读变量
-p显示指定的变量被声明的类

常见的环境变量

变量名含义常见操作
$0当前shell名称/脚本名称11、2等可以获取到传入参数
$#传入脚本的参数数量if [$# -gt 1]
$*传入脚本的所有参数
$?上条命令执行的状态码if [$? -eq 0]
$PS1命令提示符export PS1="\u@\h \w"
$HOME$HOME用户主文件夹用户主文件夹cd ~
$PATH全局命令的搜索路径PATH=$PATH:[新增路径]

配置文件加载:

image1-16817000877852.png

运算符和引用

image2-16817045772365.png

重定向

输出重定向:

>:覆盖写入文件

>>:追加写入文件

2>:将标准错误输出fd2写入文件

&>:正确和错误统一写入文件

输入重定向:

<

<<

判断命令

  • test condition
  • [ condition ]
  • [[ condition ]]

注意:

  • 中括号前后要有空格
  • 中括号中的变量,最好都是用引号括起来
  • [ 和test只是命令,只能使用自己的标志位, <,>=,只能用来比较字符串
  • [[更丰富,在整型比较中支持<,>,=,在字符串中比较中支持=~正则

分支语句

语法1:

if condition; then
​
程序段
​
elif condition; then
​
程序段
​
else
​
程序段
​
fi

语法2:

case $变量 in:
    "第一个变量内容")
    程序段
    ;;
    "第二个变量内容")
    程序段
    ;;
    *)
    程序段
    ;;
esac

循环

while循环

while condition ; do 程序段; done

until循环

until condition ; do 程序段; done

for循环

for var in [words ...]; do 程序段; done
#或者
for ((i=0;i<10;i++));   do  程序段; done

语句间的分号表示换行的意思

函数

语法1:

funcName() {内部语句;}

语法2:

function funcName() {内部语句;}

注意:

  • shell自上而下执行,函数必须在使用前定义
  • 函数获取变量和shellscript类似,$0代表函数名,后续参救通过$1、$2...获取
  • 函数内return仅仅表示函数执行状态,不代表函数执行结果
  • 返回结果一般使用echo、printf,在外面使用$()、``获取结果
  • 如果没有return,函数状态是上一条命令的执行状态,存储在$?中

模块化

使用source [函数库的路径]

Shell展开

image3.png

大括号展开

一般由三部分构成,前缀、一对大括号、后缀,大括号内可以是逗号分割的字符串序列,也可以是序列表达式{x..y[..iner]} 大括号展开(Brace Expansion){...}

#字符串序列
a{b,c,d}e   =>  abe ace ade
#表达式序列,(数字可以使用 incr调整增量,字母不行)
{1..5} => 1 2 3 4 5
​
{1..5..2} => 1 3 5
​
{a..e} => a b c d e

波浪号展开

#当前用户目录
~ => $HOME
​
~/foo => $HOME/foo
​
#指定用户的主目录
~fred/foo => 用户fred的 $HOME/foo
​
#当前工作目录
~+/foo => $PWD/foo
​
#上一个工作目录
~-foo => ${$OLDPWD-'~-'}/foo

参数展开

  1. 间接参数扩展${!parameter},其中引用的参数并不是parameter而是parameter的实际的值

  2. 参数长度${!parameter}

  3. 空参数处理

    ${parameter:-word} #为空替换
    ${parameter:=word}#为空替换,并将值赋给$parameter变量
    ${parameter:?word}#为空报错
    ${parameter:+word} #不为空替换

  4. 参数切片

    ${parameter:offset}
    ${parameter:offset:length}

  5. 参数部分删除

    ${parameter%word}#最小限度从后面截取word
    ${parameter%word}#最大限度从后面截取word
    ${parameter#word}#最小限度从前面截取word
    ${parameter##word}#最大限度从前面截取word

#!/bin/sh
​
str=abcdefg
sp1=${str##*d}
sp2=${str%%d*}  
echo $spl   #输出 efg
echo $sp2   #输出 abc

命令替换

在子进程中执行命令,并用得到的结果替换包裹的内容,形式上有两种:$(...)或...

#!/bin/bashfoo(){
    echo "asdasd"
}
​
echo $(foo)
​
a=`foo`

数学计算

使用$(())包裹数学运算表达式,得到结果并替换

#! /bin/bashecho $((1+2))   # 3

文件名展开

当有单词没有被引号包裹,且其中出现了'*', '?', 和'['字符,则shell会去按照正则匹配的方式查找文件名进行替换,如果没找到则保持不变。

#!/bin/bash
​
$ echo D*   #输出当前目录下所有以D字母开头的目录、文件

调试

set配置作用补充
-u遇到不存在的变量就会报错并停止执行-o nounset
-x运行结果之前,先输出执行的那一行命令-o xtrace
-e只要发生错误,就终止执行-o errexit
-o管道符链接的,只要一个子命令失败,整个管道命令就失败,脚本就会终止执行。-o pipefail