Shell基础简介

Linux下命令行程序叫做 Shell,除解释用户的输入命令,还可以:

  • 调用其他程序,给其他程序传递数据或参数,并获取程序的处理结果;

  • 在多个程序之间传递数据,把一个程序的输出作为另一个程序的输入;

  • Shell 本身也可以被其他程序调用。

Shell是一种脚本语言(常见的解释器有bash、sh、csh等),支持基本的编程元素,如:

  • if...else 选择结构,case 开关语句,for、while、until 循环;

  • 变量、数组、字符串、注释、加减乘除、逻辑运算等概念;

  • 函数,包括用户自定义的函数和内置函数(例如 printf、export、eval 等)。

Shell脚本也可以包含外部脚本(其他脚本文件),将外部脚本的内容合并到当前脚本。

. filename

#或

source filename

  • 两种方式的效果相同,简单起见,一般使用点号(.),但是注意点号(.)和文件名中间有一空格

  • 被包含脚本不需要有执行权限。

printf函数

除用echo输出外,printf有更强的控制方式:

  • 与c中的printf类似,但是参数不用括号,参数间用空格风格

  • 参数比控制字符多时,也会按顺序输出;

  • 参数比控制字符少时,%s用NULL代替,%d用0代替;

如:

printf '%s %d' a  #输出:a 0

printf 'Test: %s %s' a b c d e #输出:

    Test: a b

    Test: c d

    Test: e


变量基础

创建shell脚本时,必须在文件第一行指定要使用的shell:

#!/bin/bash

set -e # 遇到执行错误,退出(默认继续执行下一条)

set -u # (set -o nounset),使用未初始话变量时,脚本自动退出

脚本创建完成后,就需要执行脚本

  • chmod u+x添加X权限,调用文件执行;如./file.sh

  • 通过过sh file.sh来执行:不需要添加执行权限;

  • root用户可通过点号(.)来执行(不需执行权限),如:

. /lib/init/vars.sh

变量

  • 直接赋值即定义:count=100 #等号两边不能有空格

  • 通过$来引用变量:$count或${count}

  • readonly修饰只读变量:readonly count=100

  • unset删除变量:unset count

如:

count=1

count=`expr $count+1`

特殊变量

通过特殊变量可获取shell的参数:

  • $* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。但是当它们被双引号(" ")包含时:

    • "$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;

    • "$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。

  • shift:移动变量,将每个参数变量减一;如$3变为$2;

  • if [ -n "$1" ]:来判断参数是否已传递。

  • 更多的参数,需要加花括号引用:${10};

  • 获取最后一个参数:${!#}。

变量替换:根据变量的状态(是否为空、是否定义等)来改变它的值

三种类型变量

  • 局部变量:在脚本或命令中定义,仅在当前shell实例中有效。

  • 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量。shell脚本也可以定义环境变量。

  • shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行。


字符串类型

字符串可用单双引号:

  • 单引号的限制:

    • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;

    • 单引号字串中不能出现单引号(对单引号使用转义符后也不行)。

  • 双引号的优点:

    • 双引号里可以有变量

    • 双引号里可以出现转义字符

字符串连接

  • 直接联接两个字符串

    • newfile=${file}"new"

    • newfile=${file}${new}

  • 使用printf(使用反引号)可以进行更复杂的联接

    • newstr=`printf "%s%s" "$STR" "$USER"`

字符串操作

表达式

含义

${#str}

$str的长度

${str:position}

在$str中,从位置$position开始提取子串

${str:position:length}

在$str中,从位置$position开始提取长度为$length的子串

Position为0-n时表示从右边开始:

l${str:0-7}:取末尾7个字符

l${str:0-7:3}

${str#substring}

从变量$str的开头,删除最短匹配$substring的子串

${str##substring}

从变量$str的开头,删除最长匹配$substring的子串

${str%substring}

从变量$str的结尾,删除最短匹配$substring的子串

${str%%substring}

从变量$str的结尾,删除最长匹配$substring的子串

${str/old/new}

使用$new,来代替第一个匹配的$old

${str//old/new}

使用$new,代替所有匹配的$old

${str/#old/new}

替换开头.如果$str以$old开头,那么就用$new替换

${str/%old/new}

替换结尾.如果$str以$old结尾,那么就用$new替换

${VALUE%.*}:删除VALUE字符串中以分隔符“.”匹配的右边字符,保留左边字符。

${VALUE#*.}:删除VALUE字符串中以分隔符“.”匹配的左边字符,保留右边字符。

补充

  • “*”表示通配符,用于匹配字符串将被删除的字串。

  • “.”表示字符串中分隔符,可以为任意一个或多个字符。

  • “%”表示从左向右匹配,“#”表示从右向左匹配,“/”表示替换,都属于非贪婪匹配,即匹配符合通配符的最短结果。而“%%”、“##”和“//”,都属于贪婪匹配,即匹配符合通配符的最长结果。


数组类型

数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组)。初始化时不需要定义数组大小,数组元素的下标由0开始。数组用括号来表示,元素用"空格"符号分割开,语法格式如下:

array_name=(value1 ... valueN)

定义

myAry=(A B "CD"  1 2)

也可以使用下标来定义数组:

myAry[0]=value0

myAry[1]=value1

...

myAry[N]=valueN

读取

${myAry[index]}

echo ${myAry} 输出第一个元素

使用@ 或 * 可以获取数组中的所有元素

echo "数组的元素为: ${myAry[*]}"

echo "数组的元素为: ${myAry[@]}"

长度

获取数组长度的方法与获取字符串长度的方法相同

echo "数组长度: ${#myAry[*]}"

echo "数组元素个数: ${#myAry[@]}"

删除操作

清除某个元素:unset myAry[1],这里清除下标为1的数组;

清空整个数组:unset myAry;

切片访问

${array[@]:起始位置:长度}

  • 中间以":"隔开,

    • 起始位置省略从0开始;

    • 长度省略,就取后面所有的项;

  • 切片后返回的是字符串,可以通过 新数组=(${旧数组[@]:索引:长度})来获取

  • 起始位置可以为负数,但必须以放在()中,长度不能为负数

${myAry[@]::4}    #获取前四个元素

${myAry[@]:(-2)}    #获取后两个元素

newAry=${myAry[@]:1:4}    #生成新的切片

模式替换

${数组名[@或*]/模式/新值}

例如:${myAry[@]/2/98}

数组遍历

数组遍历我们使用for语句来演示:

for v in ${myAry[@]}; do

  echo $v;

done


运算符说明

算术运算符:原生bash不支持简单的数学运算,但可以通过其他命令(如 awk 和 expr)来实现 :

  • +、-、*、/、%

  • =、==、!=

 expr是一款表达式计算工具,使用它可以完成表达式的求值操作:

  • 在 expr中的 表达式与运算符之间要有空格,否则错误;

  • 在[ $a == $b ]与[ $a != $b ]中,要需要在方括号与变量以及变量与运算符之间也需要有空格, 否则错误。

如:

echo `expr $a + $b`

echo `expr $a \* $b`  #乘号要转义

val=`expr 10 - 3`    #表达式需要用反引号(`,~键那个)括起来

关系运算符:只支持数字(或值为数字的字符串)

  • -eq:两个数是否相等,相等返回 true。

  • -ne:两个数是否相等,不相等返回 true。

  • -gt:左边的数是否大于右边的。

  • -lt:左边的数是否小于右边的。

  • -ge:左边的数是否大等于右边的。

  • -le:左边的数是否小于等于右边的。

如:

[ 5 -eq 3 ] 返回 false

[ 5 -ne 3 ] 返回 true  #方括号与变量以及变量与运算符之间也需要有空格

布尔运算符

  • !:非, [ !false ]为true

  • -o:或

  • -a:与, [ $a -a $b ],都为true是为true

字符串运算符

  • =:两个字符串是否相等,相等返回 true。

  • !=:两个字符串是否相等,不相等返回 true。

  • -z:字符串长度是否为0,为0返回 true。

  • -n:字符串长度是否为0,不为0返回 true。

  • [ str ]:字符串是否为空,不为空返回 true。

如,以a="test"为例

[ -z $a ] 返回 false

[ $a ] 返回 true

文件测试运算符:检测文件的各种属性

  • -b file:文件是否是块设备文件,如果是,则返回 true。

  • -c file:文件是否是字符设备文件,如果是,则返回 true。

  • -d file:文件是否是目录,如果是,则返回 true。

  • -f file:文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。

  • -r file:文件是否可读,如果是,则返回 true。

  • -w file:文件是否可写,如果是,则返回 true。

  • -x file:文件是否可执行,如果是,则返回 true。

  • -s file:文件是否为空(文件大小是否大于0),不为空返回 true。

  • -e file:文件(包括目录)是否存在,如果是,则返回 true。

  • -g file:文件是否设置了 SGID 位,如果是,则返回 true

  • -k file:文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。

  • -p file:文件是否是具名管道,如果是,则返回 true。

  • -u file:文件是否设置了 SUID 位,如果是,则返回 true。

如:

[ -r $file ]     #是否可读

[ -e $file ]    #是否存在


条件语句

shell语句默认使用回车分隔(每条语句一行),若要在一行中输入多条语句可通过分号分隔实现:

if [ *** ]; then

while [ *** ]; do

针对数字与字符串判断有扩展特性,放在判断条件时与if/while等间要保证有空格:

  • 双括号(( expression )):用于数学表达式,内部可是任意的数学计算或比较表达式

    if (( $var**2 > 90 ))

    then

     ((var2=$var**2))

    fi

  • 双方括号[[ expression ]]:expression两边要加空格,用于字符串处理

    while [[ "$a" > "$b" ]] 

  • 方括号[ expr ]:逻辑判断(见运算符说明部分)

    if [ -d file ] 条件检测

if语句

if  <Condition>

then

    Command

else

    Command

fi

case语句

case 值 in

模式1)

    command...

    ;;

模式2)

    command...

    ;;

*)

    command...

    ;;

esac

  • 取值后面必须为关键字 in,每一模式必须以右括号结束。

  • 取值可以为变量或常数;匹配某一模式后,执行其后所有命令直至 ;;(双分号)。

  • 如果无一模式匹配,执行*后的命令。

如:

for a in root xugd test none; do

    echo $a

    case $a in

    root)

        echo admin

        ;;

    xugd | test ) #多个值可用|分隔

        echo normal

        ;;

#   *)

#       echo default

#       ;;

    esac

done

for循环

for循环有两种常用用法,for...in与for((赋值;条件;运算语句)) 

for var in list # for((赋值;条件;运算语句)) 

do

  commands

done

示例:循环十次

for((i=1;i<=10;i++));do 

    echo $(expr $i \* 3 + 1);

done

for i in $(seq 1 10)

do 

    echo $(expr $i \* 3 + 1);

done

#for i in {1..10};do

for i in 1 2 3 4 5;do    #直接把值列出即可(用空格分隔)

    echo $(expr $i \* 3 + 1);

done

示例:枚举文件

for file in /proc/*; do

    echo $file

done

for file in $(ls *.sh); do

    echo $file

done

while循环

while <condition>

do

action

done;

例:

i=10;

while [[ $i -gt 5 ]]; do

    echo $i;

    ((i--));

done; 

until循环

until <condition>

do 

action

done

例:

a=10;

until [[ $a -lt 0 ]];do

    echo $a;

    ((a—));

done; 

# break 命令不执行当前循环体内break下面的语句从当前循环退出。

# continue 命令是程序在本循体内忽略下面的语句,从循环头开始执行。


shell函数

Shell函数必须先定义后使用,function关键字是可选的:

[function] function_name () {

    list of commands

    [ return value ]

}

注意:

  • 调用函数只需要给出函数名,不需要加括号;

  • 函数返回值,可以显式增加return语句;如果不加,会将最后一条命令运行结果作为返回值;

  • Shell 函数返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败;

  • 函数的参数可以通过 $n  得到;

  • 像删除变量一样,删除函数也可以使用 unset 命令,不过要加上 .f 选项。


Echo输出控制

通过echo可方便输出,并控制颜色格式:

  • -e 用来开启echo中的转义

  • 设置颜色的格式:

    • echo -e "\033[字背景颜色;文字颜色m字符串"

    • echo -e "\e[0m":恢复默认

输出红色字体 abc,背景色不变;然后还原

echo -e '\033[0;31;1m abc \033[0m'

  • 文字颜色后面有个m

  • 字符串前后可以没有空格,如果有的话,输出也是同样有空格

字颜色:30—–37

  • echo -e “\033[30m 黑色字 \033[0m”

  • echo -e “\033[31m 红色字 \033[0m”

  • echo -e “\033[32m 绿色字 \033[0m”

  • echo -e “\033[33m 黄色字 \033[0m”

  • echo -e “\033[34m 蓝色字 \033[0m”

  • echo -e “\033[35m 紫色字 \033[0m”

  • echo -e “\033[36m 天蓝字 \033[0m”

  • echo -e “\033[37m 白色字 \033[0m”

字背景颜色范围:40—–47

  • echo -e “\033[40;37m 黑底白字 \033[0m”

  • echo -e “\033[41;37m 红底白字 \033[0m”

  • echo -e “\033[42;37m 绿底白字 \033[0m”

  • echo -e “\033[43;37m 黄底白字 \033[0m”

  • echo -e “\033[44;37m 蓝底白字 \033[0m”

  • echo -e “\033[45;37m 紫底白字 \033[0m”

  • echo -e “\033[46;37m 天蓝底白字 \033[0m”

  • echo -e “\033[47;30m 白底黑字 \033[0m”

控制选项说明

  • \33[0m 关闭所有属性

  • \33[1m 设置高亮度

  • \33[4m 下划线

  • \33[5m 闪烁

  • \33[7m 反显

  • \33[8m 消隐

  • \33[30m — \33[37m 设置前景色

  • \33[40m — \33[47m 设置背景色

  • \33[nA 光标上移n行

  • \33[nB 光标下移n行

  • \33[nC 光标右移n行

  • \33[nD 光标左移n行

  • \33[y;xH设置光标位置

  • \33[2J 清屏

  • \33[K 清除从光标到行尾的内容

  • \33[s 保存光标位置

  • \33[u 恢复光标位置

  • \33[?25l 隐藏光标

  • \33[?25h 显示光标

猜你喜欢

转载自blog.csdn.net/alwaysrun/article/details/88049763