Shell

Shell的变量

  • 本地变量 生效范围为当前shell进程,对当前shell之外的其他shell进程 包括当前shell的子shell进程和父shell进程均无效。可以使用set查看当前所有变量
  • 环境变量 生效范围为当前shell进程及其子进程
    • 使用 export name=VALUEdeclare -x name=VALUE 创建或转换环境变量
  • 局部变量 生效范围为当前shell进程中某函数的作用范围中。使用local name=VALUE定义局部变量
  • 位置变量 用于执行脚本时传参
  • 特殊变量 shell内置的特殊变量

    • $0 获取脚本执行时的路径
    • $? 获取上一条指定的执行返回码
    • $* 把传递给脚本的所有参数 视为一个字符串
    • $@ 把传递给脚本的所有参数 每一个参数视为每一个独立的字符串
    • $# 传递给脚本的参数数量

    • $$ 获取当前shell的进程号

    • $! 获取执行的上一个指令的pid
    • $_ 获取上一个执行的命令或脚本的最后一个参数
  • 只读变量 只读变量不能被修改,不能unset销毁
    • readonly namedeclare -r name创建只读变量
# 变量的引用
[root@stardust ~]# echo $name
[root@stardust ~]# echo ${name}


# 命令结果引用
[root@stardust ~]# echo `date` 
[root@stardust ~]# echo $(date)


# 销毁变量
[root@stardust ~]# unset name

Shell的算数运算

shell默认不支持浮点运算,浮点运算需要使用awkbc

[root@stardust ~]# let var=num1+num2        # let不会输出结果 需要复制给变量

[root@stardust ~]# echo $[RANDOM%30]        # shell内置随机数生成器 1-32767

[root@stardust ~]# echo $((2+3))

[root@stardust ~]# expr 123 + 33 / 3 

Shell条件判断

条件测试

  • test EXPRESSION
  • [ EXPRESSION ]
  • [[ EXPRESSION ]]

数值测试

  • -eq 等于
  • -ne 不等于
  • -lt 小于
  • -le 小于等于
  • -gt 大于
  • -ge 大于等于

字符测试

  • ==/= 等值测试
  • != 不相等
  • =~ 左侧字符是否能被右侧的PATTERN所匹配 只能于[[ ]]中使用
  • -z "STRING" 若字符为空 为真
  • -n "STRING" 若字符串不为空 为真

文件测试

  • -e 是否存在 不分类型
  • -s 是否存在且非空文件
  • -b 是否存在且为块设备
  • -c 是否存在且为字符设备
  • -f 是否存在且为普通文件
  • -d 是否存在且为目录
  • -S 是否存在且为套接字
  • -p 是否存在且为管道
  • -L -h 是否存在且为软链接文件
  • -g 是否存在且被设置了sgid
  • -u 是否存在且被设置了suid
  • -k 是否存在且被设置了sticky
  • -r 是否存在且可读
  • -w 是否存在且可写
  • -x 是否存在且可执行
  • -t fd 文件描述符是否打开且与某终端相关
  • -N 文件自上一次被读取后是否被修改(重定向写入)过
  • file1 -ef file2 判断两个文件是否指向同一个设备上的相同inode
  • file1 -nt file2 判断file1是否比file2时间戳更新
  • file1 -ot file2 判断file1是否比file2时间戳更旧

逻辑运算

  • && -a
  • || -o
  • !

Shell的语句

if分支语句

# 由上至下匹配,一旦匹配不再执行后面代码

if CONDITION1; then
    COMMAND
elif CONDITION2; then
    COMMAND
esle
    COMMAND
fi

case分支语句

# 由上至下匹配,一旦匹配不再执行后面代码
# PAT部分不支持正则,但是支持glob机制 `*, ?, [], |`等

case 变量引用 in
    PAT1|pat1)
        分支1
        ;;
    PAT2|pat2)
        分支2
        ;;
    *)
        默认分支
        ;;
esac

for循环语句

# 列表生产方式
#    [1] 直接给出列表 如 `a d c f`
#    [2] 返回列表的命令 如`seq 10`,`ls *`
#    [3] 变量引用 `$@, $*`
#    [4] glob 如 `{1..10}`

for 变量名 in 列表; do
    循环体
done
C语言型结构
# 变量初始化仅在进入循环时执行一次
# 每轮循环结束后会先进行变量修正运算,然后再进行条件判断

for ((变量初始化;条件判断表达式;修正变量表达式)); do
    循环体
done
=======================================================================
# demo 求100以内数字的和

#!/bin/bash
sum=0
for ((i=1;i<101;i++));do
    ((sum=sum+i))
done
echo $sum
简写结构
# 正常结构中的"in 取值列表"可省略,省略时相当于`for n in "$@"`,循环列表为命令行参数列表

# demo 打印传递给脚本的参数

for VAR;do
    echo $VAR
done
[root@stardust ~]# sh test.sh  a b c d 
a
b
c
d

while循环语句

# 若条件为真 则一直执行循环体

while CONDITION; do
    循环体
done
遍历文件内容
# 通过输入重定向遍历文件
while read VAR; do
    循环体
done < /PATH/TO/FILE


# 通过输出重定向遍历文件
cat /PATH/TO/FILE | while read VAR; do
    循环体
done


# until同样支持此用法 不过需要取反`until ! read VAR`

until循环语句

# 若条件为假 则一直执行循环体

until CONDITION; do
    循环体
done

Shell的函数

# 语法一
function FUNC_NAME {
    函数体
    return [N]
}

# 语法二
FUNC_NAME() {
    函数体
    return [N]    
}


# return 返回自定义函数执行状态码,只能返回0-255之间的整数。
# 如果没有显式的指定返回状态码,则返回函数最后一条指令的状态码


# 函数的传参 `FUNC arg1 arg2…argN`
# 函数参数的调用 在函数内 `$1 $2… $@ $*`

Shell的数组

能够存储多个元素的连续的内存空间

# 定义数组
ARRAY=(arg1 arg2 … argN)

# 通过read创建数组
read -a ARRAY

# 打印整个数组
echo ${ARRAY[*]}
echo ${ARRAY[@]}

# 数组的赋值与修改
ARRAY[INDEX]=VALUE

# 查看数组长度
echo ${#ARRAY[*]}

# 数组的删除
unset ARRAY
unset ARRAY[INDEX]

# 数组的切片  N1为起始索引位置 N2为截取元素个数
# N2可省略 表示截取到最后一个元素
echo ${ARRAY[*]:N1:N2}

# 打印数组最后N个元素
echo ${ARRAY[*]: -N}

# 数组元素的替换 使用的是变量子串操作
echo ${ARRAY[*]/pat1/sub1}

Shell的变量子串操作

以下操作适用于字符串操作和数组操作。支持使用glob 如*,[],|

变量切片和长度获取

# `${#string}` 显示变量长度
echo ${#string}

# 变量的切片  N1为起始索引位置 N2为截取元素个数
# N2可省略 表示截取到最后一个元素
echo ${var:N1:N2}

# 取最后N个元素 `-N`前必须有空格
echo ${var: -N}

变量删除替换操作

# 测试字符串数据
[root@stardust tools]# test=abcABC123abcABC

# ${string#substring} 从string开头删除最短匹配字符串
# ${string##substring} 从string开头删除最长匹配字符串
[root@stardust tools]# echo ${test#a*c} 
ABC123abcABC
[root@stardust tools]# echo ${test##a*c}
ABC

# ${string%substring} 从string结尾删除最短匹配字符串
# ${string%%substring} 从string结尾删除最长匹配字符串
[root@stardust tools]# echo ${test%a*C} 
abcABC123
[root@stardust tools]# echo ${test%%a*C}
===========================================================================
# 测试字符串数据
[root@stardust tools]# test="root:x:0:0:root:/root:/bin/bash:root"

# ${parameter/pattern/string} 替换第一个匹配的字符串
[root@Stardust ~]# echo ${test/root/ROOT}                          
ROOT:x:0:0:root:/root:/bin/bash:root

# ${parameter//pattern/string} 替换所有匹配的字符串
[root@Stardust ~]# echo ${test//root/ROOT}
ROOT:x:0:0:ROOT:/ROOT:/bin/bash:ROOT

# ${parameter/#pattern/string} 行首锚定 匹配开头第一个字段
# ${parameter/%pattern/string} 行尾锚定 匹配结尾第一个字段

# 以上多种形式`/string`部分可以省略 表示替换为空,即删除
[root@Stardust ~]# echo ${test/root} 
test::x:0:0:root:/root:/bin/bash:root

[root@Stardust ~]# echo ${test//root} 
test::x:0:0::/:/bin/bash:

字符串大小写转换

# 把所有字母转换为大写
[root@Stardust ~]# echo ${var^^}

# 把所有字母转换为小写
[root@Stardust ~]# echo ${var,,}

变量子串赋值

# 如果变量为空或未设定, 返回default。存在则返回变量的值
echo ${var:-default}

# 如果变量为空或未设定, 给变量赋值默认值default
echo ${var:=default}

# 如果变量存在且非空则返回default。变量为空或未设定,不做任何操作。
echo ${var:+default}

# 如果变量为空或未设定, 返回错误信息
echo ${var:?error_info}

Shell的特殊关键字

shift(变量左移)

# `shift [N]` shift会将当前位置的变量销毁,并将后面位置的变量依次向前移动N位

# 变量移位测试代码
#!/bin/bash  
while [ $# != 0 ]
do  
    echo "第一个参数为:$1,参数个数为:$#"  
    shift  
done  


# 执行结果 $1在不断变化 变量数量在不断减少
[root@stardust ~]# sh shift.sh a b c d e f g
第一个参数为:a,参数个数为:7
第一个参数为:b,参数个数为:6
第一个参数为:c,参数个数为:5
第一个参数为:d,参数个数为:4
第一个参数为:e,参数个数为:3
第一个参数为:f,参数个数为:2
第一个参数为:g,参数个数为:1
=======================================================================
# 变量移位测试代码
#!/bin/bash
echo "变量个数 $#  变量为 $*"
shift
echo "变量个数 $#  变量为 $*"
shift 2
echo "变量个数 $#  变量为 $*"
shift 3
echo "变量个数 $#  变量为 $*"


# 执行结果 第一次销毁1个变量 第二次销毁2个 第三次销毁3个
[root@stardust ~]# sh shift_test.sh a b c d e f g
变量个数 7  变量为 a b c d e f g
变量个数 6  变量为 b c d e f g
变量个数 4  变量为 d e f g
变量个数 1  变量为 g

read(命令行读入数据)

# `read`支持指定多个形参 接收多个实参
[root@stardust ~]# read arg1 arg2 arg3


# `-p 'PROMPT'` 指定提示信息
[root@stardust ~]# read -p "message:" arg1 arg2 arg3


# `-t TIMEOUT` 设定超时时间
[root@stardust ~]# read -t

sh(调用shell解释器)

[root@stardust ~]# sh -n        # 检查语法错误 不能检查出逻辑错误
[root@stardust ~]# sh -x        # 调试执行

exit(退出程序并返回状态码)

  • exit [N] 自定义退出状态码
  • 脚本中一旦遇到exit命令,脚本会立即终止。退出状态码取决于exit命令后面的数字
  • 如果脚本未给定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

break(跳出循环)

  • break [N] 跳出循环
  • [N]代表层数,跳出N层循环

continue(执行下一次循环)

  • continue [N] 提前结束循环 继续执行下一次循环
  • [N]代表层数,提前结束N层循环,继续执行下一次循环

source(读取其他脚本内容)

使用source.读取其他脚本内容,相当于python中的import

  • source /PATH/TO/FILE
  • . /PATH/TO/FILE




posted @ 2017-11-29 01:27  Last_Stardust  阅读(161)  评论(0编辑  收藏  举报