Shell编程

第一个shell脚本:
#!/bin/bash
echo "hello world"
运行shell脚本的三种方法:
  • 方法1:chmod +x ./test.sh;./test.sh -作为可执行程序,需要执行权限

  • 方法2:source test.sh -在当前 bash 环境下读取并执行文件中的命令,无需执行权限。或 . test.sh

  • 方法3:bash test.sh -打开一个子shell来执行文件中的命令,无需执行权限

在shell语法中执行linux命令:
  • 方法1:echo `pwd`

  • 方法2:echo $(pwd)

变量使用:
  • 变量定义:val=jack 等价于 val='jack' 等价于 val="jack";=两边不允许有空格

  • 变量引用:echo $val 等价于 echo ${val} 推荐加{} 有助于识别变量边界

  • 只读变量:readonly val

  • 删除变量:unset val

  • 字符串拼接:echo 'hello '${val}" world"

  • 字符串切片:echo ${val:1:3}

  • 字符串截取:路径处理时常用

    # 字符串截取(界定字符本身也会被删除)
    str="www.runoob.com/linux/linux-shell-variable.html"
    echo "str   : ${str}"
    echo "str#*/   : ${str#*/}"   # 从 字符串开头 删除到 左数第一个'/'
    echo "str##*/   : ${str##*/}"  # 从 字符串开头 删除到 左数最后一个'/'
    echo "str%/*   : ${str%/*}"   # 从 字符串末尾 删除到 右数第一个'/'
    echo "str%%/*   : ${str%%/*}"  # 从 字符串末尾 删除到 右数最后一个'/'
    # 输出结果
    str     : www.runoob.com/linux/linux-shell-variable.html
    str#*/ : linux/linux-shell-variable.html
    str##*/ : linux-shell-variable.html
    str%/* : www.runoob.com/linux
    str%%/* : www.runoob.com
数组使用:
  • 数组定义:array_name=(value0 value1 value2 value3)

  • 数组元素值获取:valuen=${array_name[n]}

  • 获取数组所有元素:echo ${array_name[@]} 等价于 echo ${array_name[*]}

  • 获取数组元素个数:length=${#array_name[*]}

    #!/bin/bash
    my_arry=(a b "c","d" abc)
    # 循环输出数组
    for i in ${my_arry[@]};
    do
     echo $i
    done
    # while循环: let j++自增; []左右均有空格
    j=0
    while [ $j -lt ${#my_arry[@]} ]
    do
     echo ${my_arry[$j]}
    let j++
    done
注解:单行使用#
脚本参数传递:
#!/bin/bash
# 获取脚本参数个数
echo $#
# 获取某个参数的值: $1、$2、... $n
echo $1
# $*获取所有参数:但是所有参数拼成的单个字符串
for i in "$*";do
echo $i
done
# $@获取所有参数:传递多个参数非拼合
for i in $@;do
echo $i
done
# 显示上个命令的执行状态:0表示没有错误,其他值表示有错误; 或函数的返回值
echo $?

本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收.

表达式计算:
  • expr 5 + 6:运算间要有空格 等价于$[1+2]

  • r=$[a+b]:无需空格

  • 对于用反引号括起的表达式需要赋值给变量或直接echo才能使用:val=`expr 5 + 6`

  • val=$((1+2)):无需空格

  • val=$(expr 5 + 6):相比第3种,更推荐这种

键盘输入信息:read -p "input a val:" a 获取键盘输入赋值给a,-p设置提示信息
算术运算符:
  • '*':使用特殊运算符要转义

  • ==、!=:方括号之间要有空格

    if [ $a != $b ]
    then
      echo "a 不等于 b"
    fi
关系运算符:只支持数字不支持非数字的字符串
运算符说明举例
-eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
-ne 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。
a=10
b=20
if [ $a -eq $b ]
then
  echo "$a -eq $b : a 等于 b"
else
  echo "$a -eq $b: a 不等于 b"
布尔运算符:
运算符说明举例
! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
-o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。
逻辑运算符: 作用上与布尔运算符一样,但写法上不同,逻辑运算符用在[[]]中,用在[]中会报错应用布尔运算符替换
运算符说明举例
&& 逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
|| 逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true
1、进行数值比较时,可以使用 [ expression1 OPexpression2 ],OP 可以为 -gt、-lt、-ge、-le、-eq、-ne 也可以使用 ((expression1 OP expression2)),OP 可以为 >、<、>=、<=、==、!=。这几个关系运算符都是测试整数表达式 expression1 和 expression2 之间的大小关系。
2、 >、<、==、!= 也可以进行字符串比较。
3、进行字符串比较时,== 可以使用 = 替代。
4、 == 和 !=进行字符串比较时,可以使用 [ string1 OP string2 ] 或者 [[ string1 OP string2 ]] 的形式。
5、 > 和 < 进行字符串比较时,需要使用[[ string1 OP string2 ]] 或者 [ string1 OP string2 ]。也就是使用 [] 时,> 和 < 需要使用反斜线转义。
[] 表达式
注意:在 [] 表达式中,常见的 >, < 需要加转义字符,表示字符串大小比较,以 acill 码位置作为比较。不直接支持 >, < 运算符,还有逻辑运算符 || 、&& ,它需要用 -a[and] –o[or] 表示。
[[ ]] 表达式
注意:[[]] 运算符只是 [] 运算符的扩充。能够支持 >, < 符号运算不需要转义符,它还是以字符串比较大小。里面支持逻辑运算符:|| && ,不再使用 -a -o。
判断字符串是否为空:
  • -n:字符串长度不为0返回true(对于未定义变量和""空串均为false). if [ -n "$a" ] 或 if [[ -n $a ]] 禁用 if [ -n $a ]. 建议使用双括号

  • -z:字符串长度为0返回true(对于未定义变量和""空串均为true) . if [ -z $a ] 或 if [[ -z $a ]] 推荐后者

  • $:直接使用变量判断长度不为0返回true. 等价于 -n. if [ $a ] 或 if [[ $a ]] 推荐后者

  • 貌似无法区分变量是否存在与变量是否为空字符串,对于未定义的变量默认值为空字符串

文件测试运算符:建议if判断均使用双括号
  • -d:判断是否为目录,若是为true

  • -f:判断是否为文件,若是为true

  • -r/-w/-x:判断文件是否可读可写可执行,若是为true

  • -s:判断文件是否非空(大小>0)

  • -e:判断文件/目录是否存在,若存在为true

echo输出命令:自动在末尾添加换行符
  • echo -e "OK! ":开启转义(默认原样输出).

  • echo -e "OK! c"; echo "jack":c不换行

  • 单引号:任何字符原样输出(换行符、tab符等文本格式符除外),引用变量无效,引用转义字符无效(eg:"原样输出)

  • 反引号``:将一个命令的标准输出插在原命令行中. 或者$(...)结构括起来,其中,$(...)格式受到POSIX标准支持,也利于嵌套。 

  • 双引号:能引用变量,能引用转义符,能引用文本格式符

  •  能否引用变量能否引用转义符能否引用文本格式符(如:换行符、制表符)
    单引号
    双引号
    无引号
printf格式化输出:
  • 默认不会在末尾添加换行符,以空格分隔参数

  • printf "%-10s %-8s %-4.2f " 郭靖 男 66.1234

  • %s %c %d %f都是格式替代符

  • %-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。

  • %-4.2f 指格式化为小数,其中.2指保留2位小数。

read输入命令:
  • read 命令一个一个词组地接收输入的参数,每个词组需要使用空格进行分隔;如果输入的词组个数大于需要的参数个数,则多出的词组将被作为整体为最后一个参数接收。

  • -p 输入提示文字;-n 输入字符长度限制(达到6位,自动结束);-t 输入限;-s 隐藏输入内容

重定向输入输出:
> 重定向输出到某个位置,替换原有文件的所有内容。
>> 重定向追加到某个位置,在原有文件的末尾添加内容。
< 重定向输入某个位置文件。
2> 重定向错误输出。
2>> 重定向错误追加输出到文件末尾。
&> 混合输出错误的和正确的都输出。
command > file 2>&1:将 stdout 和 stderr 合并后重定向到 file

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。

放在>后面的&,表示重定向的目标不是一个文件,而是一个文件描述符.换言之 2>1 代表将stderr重定向到当前路径下文件名为1的regular file中,而2>&1代表将stderr重定向到文件描述符为1的文件(即/dev/stdout)中,这个文件就是stdout在file system中的映射.而&>file是一种特殊的用法,也可以写成>&file,二者的意思完全相同,都等价于 >file 2>&1

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。如果希望屏蔽 stdout 和 stderr,可以这样写:
command > /dev/null 2>&1
命令说明
command > file 将输出重定向到 file。
command < file 将输入重定向到 file。
command >> file 将输出以追加的方式重定向到 file。
n > file 将文件描述符为 n (0/1/2)的文件重定向到 file。
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m 将输出文件 m 和 n 合并。
n <& m 将输入文件 m 和 n 合并。
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。
test命令:if test $val1 == $val2 等价于 if [ $val1 == $val2 ]
shell条件判断除空串和未定义变量为false,其余均为true(包括零)

shell 语言中 0 代表 true,0 以外的值代表 false

流程控制:
a=10
b=20
if [ $a == $b ]
then
  echo "a 等于 b"
elif [ $a -gt $b ]
then
  echo "a 大于 b"
elif [ $a -lt $b ]
then
  echo "a 小于 b"
else
  echo "没有符合的条件"
fi
# 写成一行
if [ $a == $b ]; then echo "a 等于 b"; else echo "a 不等于 b"; fi

for循环:

for loop in 1 2 3 4 5
do
   echo "The value is: $loop"
done
# 写成一行
for var in item1 item2 ... itemN; do command1; command2… done;
# 写法2:
for((assignment;condition:next));do
  command_1;
  command_2;
  commond_..;
done;
for((i=1;i<=5;i++));do
   echo "这是第 $i 次调用";
done;
# 通常情况下 shell 变量调用需要加 $,但是 for 的 (()) 中不需要

while循环:

int=1
while(( $int<=5 )) 等价于  while [ $int -le 5 ]
do
   echo $int
  let int++
done
# 从键盘读取输入知道ctrl+d终止
while read FILM
do
   echo "是的!$FILM 是一个好网站"
done

case:

case 值 in
模式1)
  command1
  command2
  command3
  ;;
模式2)
  command1
  command2
  command3
  ;;
*)
  command1
  command2
  command3
  ;;
esac
# break或continue的使用
while :
do
   echo -n "输入 1 到 5 之间的数字:"
  read aNum
  case $aNum in
       1|2|3|4|5) echo "你输入的数字为 $aNum!"
      ;;
      *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
          break # 或continue
           echo "hah"
      ;;
   esac
done
函数:
[ function ] funname [()]
{
  action;
  [return int;]
}
1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255
--- 示例1:
funWithReturn(){
   echo "这个函数会对输入的两个数字进行相加运算..."
   echo "输入第一个数字: "
  read aNum
   echo "输入第二个数字: "
  read anotherNum
   echo "两个数字分别为 $aNum$anotherNum !"
  return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
注意:所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。

--- 函数参数:
funWithParam(){
   echo "第一个参数为 $1 !"
   echo "第二个参数为 $2 !"
   echo "第十个参数为 $10 !"
   echo "第十个参数为 ${10} !"
   echo "第十一个参数为 ${11} !"
   echo "参数总数有 $# 个!"
   echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。
--- 0为true,非0均为false
function demoFun1(){
  return 0
}
function demoFun2(){
  return 12
}

if demoFun1
then
   echo true # true
else
   echo false
fi

if demoFun2
then
   echo ture
else
   echo false # false
fi
脚本引用:在脚本中执行其他脚本

. test1.sh 等价于 source test1.sh

原文地址:https://www.cnblogs.com/luckyboylch/p/12482129.html