shell编程基础总结

elltor 2020年12月10日 352次浏览

shell是一种特殊功能的程序,它介于用户和unix/linux操作系统内核程序(kernel)之间的一个接口. 通过SSH服务连接到shell就可进行远程操作了。

shell中的变量

  1. 用户自定义变量, 用户在bash窗口或者shell脚本中临时定义的变量
  2. 位置变量, $0,$1,$2....用来获取传入参数及程序名称($0)
  3. 预定义变量(系统变量), $#,$*,$@,$?,$$,$!这些变量只能使用不能修改
  4. 环境变量, 系统中默认存在的变量如:$PWD, $PATH, 可以通过export导出, 导出的变量可以穿透多层bash/shell。一般变量可以直接在shell中赋值创建(如:a=1)或使用set a=1,二者是等价的,如果想删除变量使用unset <变量名>
变量名含义
$#命令行参数数量
$0当前程序(脚本)名称, 带路径, 通过sh/bash执行的脚本名称中不含路径
$?前一个命令或函数的返回值
$*以 "参1 参2 参3 ..." 返回所有参数, 此时所有参数是以空格分割的一个字符串
$@以"参1" "参2" "参3" ...返回所有参数, 此时每个参数都是一个字符串
$$本程序(脚本)的进程号PID)
$!上个命令的进程号

几个特殊引用

  1. 双引号: 括起来的字符除了 $(美元符)、\(反引号)、"(双引号)、`(反引号)之外其他的均视为普通字符对待.
  2. 单引号: 括起来的字符都视为普通字符,普通字符直接被打印
  3. 反引号: 反引号括起来的字符串会被shell解释为命令, 就像在shell中输入命令一样, 注意: 在反双引号中不能用命令的别名

脚本中常用变量替换

  1. ${var} 取出var变量的值
  2. ${var:-var2} var为空或已被删除或未定义, 则表达式返回var2, 不改变var的值
  3. ${var:+var2} var未定义, 则返回var2, 不改变var的值
  4. ${var:=var2} var为空或已被删除或未定义, 则表达式返回var2, 改变var的值!, 如果已被删除或未定义会重新创建变量
  5. ${var:?msg} 如果var为空或已被删除或未定义, 则在控制台标准输出打印msg, 可以用来检测变量var是否被赋值. 当出现这种替换, 脚本将停止运行.

字符串变量的截取

  1. ${#str} 求str的串长
  2. ${str:3} 从第3个字符截取到最后一个字符(含第3个)
  3. ${str:3:5} 从第3个字符截取到第5个字符(含第3第5个)

sehll中变量计算

  1. $(()), 在两个括号中可以放置需要计算的变量表达式
  2. $[], 在中括号中放入表达式
  3. let , let sum=1+2
  4. expr, 如: sum="expr 1 + 2", 注意: +好两端要有空格!

read -- 读取变量命令

该用在shell脚本中, 读取一个变量并赋值, 如果指定多个变量但输入参数数量超过时, 多的参数赋值在最后个接收的变量.
参数:

  • -p 后面跟提示信息, 当用户输入时显示提示信息
  • -n 指定read读入文本长度
  • -s 静默输入, 输入字符时不显示在屏幕上

echo

常用参数:

  • -n 在屏幕打印后不换行
  • -e 启用反斜杠转义功能,对\n之类转义字符进行转义,否则作为普通字符输出
  • -E 此项为缺省项, 不对转义字符做特殊处理

常用转义字符

转义字符含义
\n换行
-r回车, 换到下一行并将光标置于行首
\r制表符
\b退格,左删除
\\斜杠本身

shell中比较和判断

在shell中0代表的是真, 非零代表为假, 这一点与C/C++截然相反的.

数值比较表达式

test表达式的两种形式: test var -eq var2 [ var -eq var2 ]

test表达式含义
var -eq var2判断两变量是否相等
var -ge var2判断var是否大于等于var2
var -le var2判断var是否小于等于var2
var -gt var2判断var是否大于var2
var -lt var2判断var是否小于var2
var -ne var2判断var是否不等于var2

类型判断表达式

test表达式含义
-d file判断file是否为目录
-f file判断file是否为文件
-r file判断文件是否可读
-w file判断文件是否可写
-x file判断文件是否可以执行
-s file判断文件内容长度是否大于0

判断字符串

test表达式含义
=等于则为真
!=不相等则为真
-z 字符串字符串的长度为零则为真
-n 字符串字符串的长度不为零则为真

逻辑判断表达式

test表达式含义
!varvar=假/0, 返回真
var1 -a var2var1和var2同时为真才返回真,否则返回假
var1 -o var2var1和var2至少有一个为真是返回真,否则返回假

注意事项
变量测试表达式一般不单独使用, 常常作为for/if的条件.

shell的分支循环结构

if 结构

#!/bin/bash

let var=2
# 常用写法
if [ $var -eq 0 ]
then
    echo "var is 0"
fi

# 常用写法2
if [ $var -eq 0 ]; then
    echo "var is 0"
fi

# 直接写test方式
if test $var -eq 0
then
    echo "var is 0"
fi

# if-else
if [ $var -eq 0 ]
then
   echo "var is 0"
else
   echo "var is other number."
fi

# if-elif-else
if [ $var -eq 0 ]
then
   echo "var is 0"
elif [ $var -eq 1 ]
then
   echo "var is 1"
else
   echo "var is other number."
fi

case 结构

case结构与常见语言的switch语句相似, 不同的是每个case分支结束时用双分号;;.

#!/bin/bash

read -p "please intput a animal name: " a
# 匹配字符串
case $a in
cat)
    echo "this is a cat."
    ;;
fish)
    echo "this is a fish."
    ;;
*)
    echo "another animal."
esac

# 匹配数字
case $a in
1)
    echo "match number 1"
    ;;
2)
    echo "match number 2"
    ;;
*)
    echo "unknow number: $a"
esac

for 结构

#!/bin/bash

echo "-----------"
echo "all args:$*"
echo "all args:$@"
echo "-----------"

# 常用, $*可以替换为$@,都获取执行脚本时所有参数
for a in $*
do
    echo "$a"
done

# 循环1到5, in后面的{}中为一组内容,数字或文本都可
# {1..5} 等价于 {1,2,3,4,5}
for a in {1,2,3,4,5}
do
    echo "$a"
done

# 循环1到5
for a in 1 2 3 4 5
do
    echo "$a"
done

# C语言风格, 循环1~5
for (( i=1; i<=5; i++ ))
do
    echo "$i"
done

# -------------
# 输出当前目录中以.sh结尾的文件 
for n in `ls *.sh`
{
    echo $n
}

# 输出 1~10,{1..10} 产生1~10序列,等价于 seq 10
for a in {1..10}
{
    echo $a
}

while 结构

在while改变变量的值使用let 或 var=$[express], 其中var为一个变量,express为一个运算表达式,如1+2

**#!/bin/bash

let var=1

# 常用, 循环1~5
while [ $var -le 5 ]
do
    echo "$var"
    let var=$var+1
done

let var=1
while [ $var -le 5 ]
do
    echo "$var"
    let var++
done

until

当条件为假时执行循环, 其使用同while.

循环控制语句

中断语句:

  • break: 用来终止循环, 如果是前嵌套循环break后可以跟一个数字n, 表示退出第n重循环(最内的循环为第一重)
  • continue: 用来跳过(忽略)本次循环, 如果是嵌套循环, continue后可以跟一个数字n, 表示回到第n重循环的顶部
#!/bin/bash

let var=1

# 常用, 循环0~5
while [ $var -le 5 ]
do
    if [ $var -eq 2 ]
    then
        echo "now var=$var, break while."
        break
    fi
	
    echo "$var"
    let var=$var+1
done

echo "----------------------"

let var=1
while [ $var -le 5 ]
do
    
    if [ $var -eq 2 ]
    then
        echo "now var=$var, conticned the second cycle."
        break
    fi

    echo "$var"
    let var++
done

函数

函数的在shell中是独立的一段代码,实现一些功能的复用。

函数要点:

  • 函数可以接收参数,同shell脚本接收参数方式相同,使用$*,$@,$1
  • 函数体中获取参数的变量($*,$@,$1)获取的是函数自己的参数

定义方式

#!/bin/bash

# 定义函数方式1
fun1()
{
    echo "called fun1"
}

# 定义函数方式2
function fun2
{
    echo "called fun2"
}

#调用函数
fun1
fun2

函数实现递归

#!/bin/bash
# 通过读取脚本的第一输入参数值求其阶乘, 并输出结果 

# 递归求阶乘函数
function jie 
{
    if [ $1 -le 1 ]
    then
        echo 1
    else
        x=`jie $[$1-1]`
        echo $[$1*x]
    fi
}

# 调用计算
res=$(jie $1) # 此处函数jie接收的第一个参数为此脚本运行时的第一个参数
echo "res=$res" # 接收echo输出的返回值

数组

在shell中数组与高级编程语言中的数组时有区别的, 在声明方面可以用declare -a arr声明arr数组, 参数-a是声明数组的意思, 除此之外declare还可以声明函数, 其次当我们使用declare声明一个数组时,下标越界不会有报错提示.

declare后的参数

-a 声明数组
-i 声明integer整数
-r 声明变量定义为只读
-f 定义为函数

数组的使用

#!/bin/bash

declare -a arr[10]
# 即使下标越界(i>=10)也不会报错
for ((i=0;i<10;i++))
{   
    arr[i]=$[i+1]
}

# 输出
for ((k=0;k<10;k++))
{
    echo ${arr[k]}
}

总结

学完以上只是对shell编程的一个入门, 如果把一下常用的命令(如: awk、sed、grep、find)结合进脚本,功能就会大大增强.

在写test判断表达式时尽量每个部分之间都一个空格,以免出现格式操作。注意: expr的运算符两边是必须要留空格的。总之多留一些空格可以避免一些语法错误。

for可以遍历的内容很多, 不仅仅是数组, 在in后可以放置命令的执行结果(以空格分割)