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

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或$

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" ]:来判断参数是否已传递。

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

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

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

三种类型变量

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

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

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

字符串类型

字符串可用单双引号:

单引号的限制:

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

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

双引号的优点:

双引号里可以有变量

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

字符串连接

直接联接两个字符串

newfile=$"new"

newfile=$$

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

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

字符串操作

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

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

补充

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

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

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

数组类型

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

array_name=(value1 ... valueN)

定义

myAry=(A B "CD" 1 2)

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

myAry[0]=value0

myAry[1]=value1

...

myAry[N]=valueN

读取

$

echo $ 输出第一个元素

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

echo "数组的元素为: $"

echo "数组的元素为: $"

长度

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

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

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

删除操作

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

清空整个数组:unset myAry;

切片访问

$

中间以":"隔开,

起始位置省略从0开始;

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

切片后返回的是字符串,可以通过 新数组=($)来获取

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

$ #获取前四个元素

$ #获取后两个元素

newAry=$ #生成新的切片

模式替换

$

例如:$

数组遍历

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

for v in $; 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

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

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

done

for i in $(seq 1 10)

do

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

done

#for i in ;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

do

action

done;

例:

i=10;

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

echo $i;

((i--));

done;

until循环

until

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 显示光标

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180929G1P1Y600?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券